diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..f8271bad --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +py/src/braintrust/api/_generated/** linguist-generated=true diff --git a/.github/actions/setup-python-env/action.yml b/.github/actions/setup-python-env/action.yml index c0c3272d..4e0faecc 100644 --- a/.github/actions/setup-python-env/action.yml +++ b/.github/actions/setup-python-env/action.yml @@ -3,8 +3,9 @@ description: "Checkout, configure mise, and install dev dependencies for a given inputs: python-version: - description: "Python version to install (e.g. 3.12)" - required: true + description: "Python version to install (e.g. 3.12). Defaults to the .tool-versions pin." + required: false + default: "" runs: using: "composite" @@ -20,8 +21,8 @@ runs: with: cache: true experimental: true - install_args: python@${{ inputs.python-version }} + install_args: ${{ inputs.python-version && format('python@{0}', inputs.python-version) || '' }} - name: Install dependencies shell: bash run: | - mise exec python@${{ inputs.python-version }} -- make -C py install-dev + mise exec ${{ inputs.python-version && format('python@{0}', inputs.python-version) || '' }} -- make -C py install-dev diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 8bafd769..b64207a0 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -32,6 +32,17 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - run: bash scripts/ensure-pinned-actions.sh + api-codegen: + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Setup Python environment + uses: ./.github/actions/setup-python-env + - name: Test generator and check committed output + run: | + mise exec -- make -C py test-api-codegen check-api-client-codegen + static_checks: runs-on: ubuntu-24.04 timeout-minutes: 20 @@ -136,6 +147,7 @@ jobs: run: | mise exec python@${{ matrix.python-version }} -- python ./py/scripts/nox-matrix.py ${{ matrix.shard }} 6 \ --exclude-static-checks \ + --exclude-session test_api_codegen \ --exclude-session-prefix test_transformers transformers-py: @@ -200,6 +212,7 @@ jobs: needs: - lint - ensure-pinned-actions + - api-codegen - static_checks - smoke - nox @@ -227,6 +240,7 @@ jobs: check_result "lint" "${{ needs.lint.result }}" check_result "ensure-pinned-actions" "${{ needs['ensure-pinned-actions'].result }}" + check_result "api-codegen" "${{ needs['api-codegen'].result }}" check_result "static_checks" "${{ needs.static_checks.result }}" check_result "smoke" "${{ needs.smoke.result }}" check_result "nox" "${{ needs.nox.result }}" diff --git a/.github/workflows/update-session-weights.yaml b/.github/workflows/update-session-weights.yaml index e684c439..634bef67 100644 --- a/.github/workflows/update-session-weights.yaml +++ b/.github/workflows/update-session-weights.yaml @@ -31,6 +31,7 @@ jobs: run: | mise exec python@3.10 -- python ./py/scripts/nox-matrix.py ${{ matrix.shard }} 4 \ --exclude-static-checks \ + --exclude-session test_api_codegen \ --output-durations measured-durations-${{ matrix.shard }}.json - name: Upload measured durations uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7adeb943..7260ebf9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,6 +2,7 @@ exclude: > (?x)^( py/src/braintrust/_generated_types\.py |py/src/braintrust/generated_types\.py + |py/src/braintrust/api/_generated/.* )$ repos: diff --git a/openapi/README.md b/openapi/README.md new file mode 100644 index 00000000..fa2064c2 --- /dev/null +++ b/openapi/README.md @@ -0,0 +1,33 @@ +# Pinned Braintrust OpenAPI specification + +`spec.json` is a committed snapshot of the public specification from +[`braintrustdata/braintrust-openapi`](https://github.com/braintrustdata/braintrust-openapi). +`config.json` pins the full upstream commit, snapshot SHA-256, generator tools, generator flags, and +explicit endpoint exclusions. The generator scripts live in `py/scripts/`. Builds and package installation use the committed generated source and never fetch or run +code generation. + +From `py/`, validate and regenerate the private models offline with: + +```bash +make generate-api-client +make check-api-client-codegen +``` + +The check regenerates into a temporary directory and does not modify the worktree. + +To fetch the configured upstream commit explicitly: + +```bash +make fetch-openapi-spec +``` + +For an existing local checkout, set `BRAINTRUST_OPENAPI_ROOT` to its root. The checkout must be at the +commit pinned in `config.json`, and its specification must have the pinned hash: + +```bash +BRAINTRUST_OPENAPI_ROOT=../../braintrust-openapi make fetch-openapi-spec +``` + +To update the snapshot, first update the commit and SHA-256 in `config.json`, then fetch, regenerate, +and review both the upstream spec diff and generated model diff. Fix specification defects upstream +rather than adding Python-side normalization beyond CORS `OPTIONS` removal and configured exclusions. diff --git a/openapi/config.json b/openapi/config.json new file mode 100644 index 00000000..b043e3d5 --- /dev/null +++ b/openapi/config.json @@ -0,0 +1,59 @@ +{ + "schema_version": 1, + "spec": { + "repository": "braintrustdata/braintrust-openapi", + "path": "openapi/spec.json", + "commit": "9daf27f19d9e0340304d7a3e7d0edb28380b94c6", + "sha256": "5ec753c0263c0c44cd04f741edfc7e8bad491cc25a2113d029e84edc076520f0" + }, + "tools": { + "datamodel-code-generator": "0.72.4", + "ruff": "0.15.21", + "python": "3.14" + }, + "model_generator": { + "flags": [ + "--input-file-type=openapi", + "--output-model-type=typing.TypedDict", + "--target-python-version=3.10", + "--use-union-operator", + "--enum-field-as-literal=all", + "--use-generic-container-types", + "--use-field-description", + "--strict-nullable", + "--parent-scoped-naming", + "--no-use-closed-typed-dict", + "--disable-future-imports", + "--formatters=ruff-format" + ] + }, + "endpoint_generator": { + "schema_version": 1, + "skip_tags": { + "Proxy": { + "reason": "Proxy endpoints stream provider-specific payloads and remain on the specialized proxy path.", + "operation_ids": [ + "proxychatCompletions", + "proxycompletions", + "proxyauto", + "proxyembeddings", + "proxycredentials", + "proxy{path+}" + ] + } + }, + "supported_success_statuses": [ + "200", + "201", + "202", + "204" + ], + "supported_request_media_types": [ + "application/json" + ], + "supported_response_media_types": [ + "application/json", + "text/plain" + ] + } +} diff --git a/openapi/spec.json b/openapi/spec.json new file mode 100644 index 00000000..7f99fe09 --- /dev/null +++ b/openapi/spec.json @@ -0,0 +1,34183 @@ +{ + "openapi": "3.0.3", + "info": { + "version": "1.0.0", + "title": "Braintrust API", + "description": "API specification for the backend data server. The API is hosted globally at\nhttps://api.braintrust.dev or in your own environment.\n\nYou can access the OpenAPI spec for this API at https://github.com/braintrustdata/braintrust-openapi.", + "license": { + "name": "Apache 2.0" + } + }, + "servers": [ + { + "url": "https://api.braintrust.dev" + } + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "API key or JWT", + "description": "Most Braintrust endpoints are authenticated by providing your API key as a header `Authorization: Bearer [api_key]` to your HTTP request. You can create an API key in the Braintrust [organization settings page](https://www.braintrustdata.com/app/settings?subroute=api-keys)." + } + }, + "schemas": { + "ProjectIdParam": { + "type": "string", + "format": "uuid", + "description": "Project id" + }, + "ExperimentIdParam": { + "type": "string", + "format": "uuid", + "description": "Experiment id" + }, + "DatasetIdParam": { + "type": "string", + "format": "uuid", + "description": "Dataset id" + }, + "PromptIdParam": { + "type": "string", + "format": "uuid", + "description": "Prompt id" + }, + "PromptSessionIdParam": { + "type": "string", + "format": "uuid", + "description": "PromptSession id" + }, + "RoleIdParam": { + "type": "string", + "format": "uuid", + "description": "Role id" + }, + "GroupIdParam": { + "type": "string", + "format": "uuid", + "description": "Group id" + }, + "AclIdParam": { + "type": "string", + "format": "uuid", + "description": "Acl id" + }, + "UserIdParam": { + "type": "string", + "format": "uuid", + "description": "User id" + }, + "AgentIdParam": { + "type": "string", + "format": "uuid", + "description": "Agent id" + }, + "ProjectAutomationIdParam": { + "type": "string", + "format": "uuid", + "description": "ProjectAutomation id" + }, + "ProjectScoreIdParam": { + "type": "string", + "format": "uuid", + "description": "ProjectScore id" + }, + "ProjectTagIdParam": { + "type": "string", + "format": "uuid", + "description": "ProjectTag id" + }, + "SpanIframeIdParam": { + "type": "string", + "format": "uuid", + "description": "SpanIframe id" + }, + "FunctionIdParam": { + "type": "string", + "format": "uuid", + "description": "Function id" + }, + "ViewIdParam": { + "type": "string", + "format": "uuid", + "description": "View id" + }, + "OrganizationIdParam": { + "type": "string", + "format": "uuid", + "description": "Organization id" + }, + "ApiKeyIdParam": { + "type": "string", + "format": "uuid", + "description": "ApiKey id" + }, + "ServiceTokenIdParam": { + "type": "string", + "format": "uuid", + "description": "ServiceToken id" + }, + "AiSecretIdParam": { + "type": "string", + "format": "uuid", + "description": "AiSecret id" + }, + "EnvVarIdParam": { + "type": "string", + "format": "uuid", + "description": "EnvVar id" + }, + "McpServerIdParam": { + "type": "string", + "format": "uuid", + "description": "McpServer id" + }, + "DatasetSnapshotIdParam": { + "type": "string", + "format": "uuid", + "description": "DatasetSnapshot id" + }, + "ProjectIdQuery": { + "type": "string", + "format": "uuid", + "description": "Project id" + }, + "ProjectName": { + "type": "string", + "description": "Name of the project to search for" + }, + "ExperimentName": { + "type": "string", + "description": "Name of the experiment to search for" + }, + "DatasetName": { + "type": "string", + "description": "Name of the dataset to search for" + }, + "PromptName": { + "type": "string", + "description": "Name of the prompt to search for" + }, + "PromptSessionName": { + "type": "string", + "description": "Name of the prompt_session to search for" + }, + "RoleName": { + "type": "string", + "description": "Name of the role to search for" + }, + "GroupName": { + "type": "string", + "description": "Name of the group to search for" + }, + "AgentName": { + "type": "string", + "description": "Name of the agent to search for" + }, + "ProjectAutomationName": { + "type": "string", + "description": "Name of the project_automation to search for" + }, + "ProjectScoreName": { + "type": "string", + "description": "Name of the project_score to search for" + }, + "ProjectTagName": { + "type": "string", + "description": "Name of the project_tag to search for" + }, + "SpanIframeName": { + "type": "string", + "description": "Name of the span_iframe to search for" + }, + "FunctionName": { + "type": "string", + "description": "Name of the function to search for" + }, + "ViewName": { + "type": "string", + "description": "Name of the view to search for" + }, + "ApiKeyName": { + "type": "string", + "description": "Name of the api_key to search for" + }, + "ServiceTokenName": { + "type": "string", + "description": "Name of the service_token to search for" + }, + "AiSecretName": { + "type": "string", + "description": "Name of the ai_secret to search for" + }, + "EnvVarName": { + "type": "string", + "description": "Name of the env_var to search for" + }, + "McpServerName": { + "type": "string", + "description": "Name of the mcp_server to search for" + }, + "DatasetSnapshotName": { + "type": "string", + "description": "Name of the dataset_snapshot to search for" + }, + "OrgName": { + "type": "string", + "description": "Filter search results to within a particular organization" + }, + "Ids": { + "anyOf": [ + { + "type": "string", + "format": "uuid" + }, + { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + } + } + ], + "description": "Filter search results to a particular set of object IDs. To specify a list of IDs, include the query param multiple times" + }, + "AppLimitParam": { + "type": "integer", + "nullable": true, + "minimum": 0, + "description": "Limit the number of objects to return" + }, + "AppLimitWithDefaultParam": { + "type": "integer", + "nullable": true, + "minimum": 0, + "default": 1000, + "description": "Limit the number of objects to return" + }, + "FetchLimitParam": { + "type": "integer", + "nullable": true, + "minimum": 0, + "description": "limit the number of traces fetched\n\nFetch queries may be paginated if the total result size is expected to be large (e.g. project_logs which accumulate over a long time). Note that fetch queries only support pagination in descending time order (from latest to earliest `_xact_id`. Furthermore, later pages may return rows which showed up in earlier pages, except with an earlier `_xact_id`. This happens because pagination occurs over the whole version history of the event log. You will most likely want to exclude any such duplicate, outdated rows (by `id`) from your combined result set.\n\nThe `limit` parameter controls the number of full traces to return. So you may end up with more individual rows than the specified limit if you are fetching events containing traces." + }, + "StartingAfter": { + "type": "string", + "format": "uuid", + "description": "Pagination cursor id.\n\nFor example, if the final item in the last page you fetched had an id of `foo`, pass `starting_after=foo` to fetch the next page. Note: you may only pass one of `starting_after` and `ending_before`" + }, + "EndingBefore": { + "type": "string", + "format": "uuid", + "description": "Pagination cursor id.\n\nFor example, if the initial item in the last page you fetched had an id of `foo`, pass `ending_before=foo` to fetch the previous page. Note: you may only pass one of `starting_after` and `ending_before`" + }, + "MaxXactId": { + "type": "string", + "description": "DEPRECATION NOTICE: The manually-constructed pagination cursor is deprecated in favor of the explicit 'cursor' returned by object fetch requests. Please prefer the 'cursor' argument going forwards.\n\nTogether, `max_xact_id` and `max_root_span_id` form a pagination cursor\n\nSince a paginated fetch query returns results in order from latest to earliest, the cursor for the next page can be found as the row with the minimum (earliest) value of the tuple `(_xact_id, root_span_id)`. See the documentation of `limit` for an overview of paginating fetch queries." + }, + "MaxRootSpanId": { + "type": "string", + "description": "DEPRECATION NOTICE: The manually-constructed pagination cursor is deprecated in favor of the explicit 'cursor' returned by object fetch requests. Please prefer the 'cursor' argument going forwards.\n\nTogether, `max_xact_id` and `max_root_span_id` form a pagination cursor\n\nSince a paginated fetch query returns results in order from latest to earliest, the cursor for the next page can be found as the row with the minimum (earliest) value of the tuple `(_xact_id, root_span_id)`. See the documentation of `limit` for an overview of paginating fetch queries." + }, + "Version": { + "type": "string", + "description": "Retrieve a snapshot of events from a past time\n\nThe version id is essentially a filter on the latest event transaction id. You can use the `max_xact_id` returned by a past fetch as the version to reproduce that exact fetch." + }, + "PromptVersion": { + "type": "string", + "description": "Retrieve prompt at a specific version.\n\nThe version id can either be a transaction id (e.g. '1000192656880881099') or a version identifier (e.g. '81cd05ee665fdfb3')." + }, + "PromptEnvironment": { + "type": "string", + "description": "Filter by environment slug. Cannot be used together with `version`.\n\nFor `GET /v1/prompt`, environment resolution currently requires the request to match a single prompt. If multiple prompts match, the endpoint returns `400` (for example when `limit=1` is not set). Use `limit=1` or other filters (for example `slug`, `project_id`) to narrow results." + }, + "SummarizeScores": { + "type": "boolean", + "nullable": true, + "description": "Whether to summarize the scores and metrics. If false (or omitted), only the metadata will be returned." + }, + "ComparisonExperimentId": { + "type": "string", + "format": "uuid", + "description": "The experiment to compare against, if summarizing scores and metrics. If omitted, will fall back to the `base_exp_id` stored in the experiment metadata, and then to the most recent experiment run in the same project. Must pass `summarize_scores=true` for this id to be used" + }, + "SummarizeData": { + "type": "boolean", + "nullable": true, + "description": "Whether to summarize the data. If false (or omitted), only the metadata will be returned." + }, + "Slug": { + "type": "string", + "description": "Retrieve prompt with a specific slug" + }, + "ViewType": { + "type": "string", + "enum": [ + "projects", + "experiments", + "experiment", + "playgrounds", + "playground", + "datasets", + "dataset", + "prompts", + "parameters", + "tools", + "scorers", + "classifiers", + "logs", + "monitor", + "for_review_project_log", + "for_review_experiments", + "for_review_datasets", + null + ], + "description": "Type of object that the view corresponds to." + }, + "UserGivenName": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Given name of the user to search for. You may pass the param multiple times to filter for more than one given name" + }, + "UserFamilyName": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Family name of the user to search for. You may pass the param multiple times to filter for more than one family name" + }, + "UserEmail": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Email of the user to search for. You may pass the param multiple times to filter for more than one email" + }, + "AclObjectType": { + "type": "string", + "enum": [ + "organization", + "project", + "experiment", + "dataset", + "prompt", + "prompt_session", + "group", + "role", + "org_member", + "project_log", + "org_project", + "org_audit_logs" + ], + "description": "The object type that the ACL applies to" + }, + "AclObjectId": { + "type": "string", + "format": "uuid", + "description": "The id of the object the ACL applies to" + }, + "AclListOrgObjectType": { + "type": "string", + "enum": [ + "organization", + "project", + "experiment", + "dataset", + "prompt", + "prompt_session", + "group", + "role", + "org_member", + "project_log", + "org_project", + "org_audit_logs" + ], + "description": "The object type that the ACL applies to" + }, + "AclListOrgObjectId": { + "type": "string", + "format": "uuid", + "description": "The id of the object the ACL applies to" + }, + "AclListUserId": { + "type": "string", + "format": "uuid", + "description": "Id of the user the ACL applies to. Exactly one of `user_id` and `group_id` will be provided" + }, + "AclListGroupId": { + "type": "string", + "format": "uuid", + "description": "Id of the group the ACL applies to. Exactly one of `user_id` and `group_id` will be provided" + }, + "AclListPermission": { + "type": "string", + "enum": [ + "create", + "read", + "update", + "delete", + "create_acls", + "read_acls", + "update_acls", + "delete_acls" + ], + "description": "Each permission permits a certain type of operation on an object in the system\n\nPermissions can be assigned to to objects on an individual basis, or grouped into roles" + }, + "AclListRestrictObjectType": { + "type": "string", + "enum": [ + "organization", + "project", + "experiment", + "dataset", + "prompt", + "prompt_session", + "group", + "role", + "org_member", + "project_log", + "org_project", + "org_audit_logs" + ], + "description": "The object type that the ACL applies to" + }, + "AclListRoleId": { + "type": "string", + "format": "uuid", + "description": "Id of the role the ACL grants. Exactly one of `permission` and `role_id` will be provided" + }, + "ProjectScoreType": { + "type": "string", + "enum": [ + "slider", + "categorical", + "weighted", + "minimum", + "maximum", + "online", + "free-form" + ], + "description": "The type of the configured score", + "title": "project_score_type_single" + }, + "AISecretType": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "EnvVarObjectType": { + "type": "string", + "enum": [ + "organization", + "project", + "function" + ], + "description": "The type of the object the environment variable is scoped for" + }, + "EnvVarObjectId": { + "type": "string", + "format": "uuid", + "description": "The id of the object the environment variable is scoped for" + }, + "FunctionTypeEnum": { + "type": "string", + "enum": [ + "llm", + "scorer", + "task", + "tool", + "custom_view", + "preprocessor", + "facet", + "classifier", + "tag", + "parameters", + "sandbox", + null + ], + "default": "scorer", + "description": "The type of global function. Defaults to 'scorer'." + }, + "NullableSavedFunctionId": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "function" + ] + }, + "id": { + "type": "string" + }, + "version": { + "type": "string", + "description": "The version of the function" + } + }, + "required": [ + "type", + "id" + ], + "title": "function" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "global" + ] + }, + "name": { + "type": "string" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + } + }, + "required": [ + "type", + "name" + ], + "title": "global" + }, + { + "type": "null" + } + ], + "description": "Default preprocessor for this project. When set, functions that use preprocessors will use this instead of their built-in default." + }, + "ProjectSettings": { + "type": "object", + "nullable": true, + "properties": { + "comparison_key": { + "type": "string", + "nullable": true, + "description": "The key used to join two experiments (defaults to `input`)" + }, + "baseline_experiment_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "The id of the experiment to use as the default baseline for comparisons" + }, + "spanFieldOrder": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "object_type": { + "type": "string" + }, + "column_id": { + "type": "string" + }, + "position": { + "type": "string" + }, + "layout": { + "anyOf": [ + { + "type": "string", + "enum": [ + "full" + ] + }, + { + "type": "string", + "enum": [ + "two_column" + ] + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "object_type", + "column_id", + "position" + ] + }, + "description": "The order of the fields to display in the trace view" + }, + "remote_eval_sources": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "name": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + } + }, + "required": [ + "url" + ] + }, + "description": "The remote eval sources to use for the project" + }, + "disable_realtime_queries": { + "type": "boolean", + "nullable": true, + "description": "If true, disable real-time queries for this project. This can improve query performance for high-volume logs." + }, + "default_preprocessor": { + "$ref": "#/components/schemas/NullableSavedFunctionId" + } + } + }, + "Project": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project" + }, + "org_id": { + "type": "string", + "format": "uuid", + "description": "Unique id for the organization that the project belongs under" + }, + "name": { + "type": "string", + "description": "Name of the project" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the project" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of project creation" + }, + "deleted_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of project deletion, or null if the project is still active" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifies the user who created the project" + }, + "settings": { + "$ref": "#/components/schemas/ProjectSettings" + } + }, + "required": [ + "id", + "org_id", + "name" + ] + }, + "CreateProject": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "Name of the project" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the project" + }, + "org_name": { + "type": "string", + "nullable": true, + "description": "For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the project belongs in." + } + }, + "required": [ + "name" + ] + }, + "PatchProject": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the project" + }, + "description": { + "type": "string", + "nullable": true + }, + "user_id": { + "type": "string", + "nullable": true + }, + "settings": { + "allOf": [ + { + "$ref": "#/components/schemas/ProjectSettings" + }, + { + "description": "Project settings. Patch operations replace all settings, so make sure you include all settings you want to keep." + } + ] + } + } + }, + "InsertEventsResponse": { + "type": "object", + "properties": { + "row_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The ids of all rows that were inserted, aligning one-to-one with the rows provided as input" + } + }, + "required": [ + "row_ids" + ] + }, + "SpanType": { + "type": "string", + "nullable": true, + "enum": [ + "llm", + "score", + "function", + "eval", + "task", + "tool", + "automation", + "facet", + "preprocessor", + "classifier", + "review", + null + ], + "description": "Type of the span, for display purposes only" + }, + "SpanAttributes": { + "type": "object", + "nullable": true, + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the span, for display purposes only" + }, + "type": { + "$ref": "#/components/schemas/SpanType" + }, + "purpose": { + "type": "string", + "nullable": true, + "enum": [ + "scorer", + null + ], + "description": "A special value that indicates the span was generated by a scoring automation" + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "Human-identifying attributes of the span, such as name, type, etc." + }, + "ObjectReferenceNullish": { + "type": "object", + "nullable": true, + "properties": { + "object_type": { + "type": "string", + "enum": [ + "project_logs", + "experiment", + "dataset", + "prompt", + "function", + "prompt_session" + ], + "description": "Type of the object the event is originating from." + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "ID of the object the event is originating from." + }, + "id": { + "type": "string", + "description": "ID of the original event." + }, + "_xact_id": { + "type": "string", + "nullable": true, + "description": "Transaction ID of the original event." + }, + "created": { + "type": "string", + "nullable": true, + "description": "Created timestamp of the original event. Used to help sort in the UI" + } + }, + "required": [ + "object_type", + "object_id", + "id" + ], + "description": "Indicates the event was copied from another object." + }, + "InsertProjectLogsEvent": { + "type": "object", + "properties": { + "input": { + "nullable": true, + "description": "The arguments that uniquely define a user input (an arbitrary, JSON serializable object)." + }, + "output": { + "nullable": true, + "description": "The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question." + }, + "expected": { + "nullable": true, + "description": "The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models." + }, + "error": { + "nullable": true, + "description": "The error that occurred, if any." + }, + "scores": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "number", + "nullable": true, + "minimum": 0, + "maximum": 1 + }, + "description": "A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was covering similar concepts or not. You can use these scores to help you sort, filter, and compare logs." + }, + "metadata": { + "type": "object", + "nullable": true, + "properties": { + "model": { + "type": "string", + "nullable": true, + "description": "The model used for this example" + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags to log" + }, + "metrics": { + "type": "object", + "nullable": true, + "properties": { + "start": { + "type": "number", + "nullable": true, + "description": "A unix timestamp recording when the section of code which produced the project logs event started" + }, + "end": { + "type": "number", + "nullable": true, + "description": "A unix timestamp recording when the section of code which produced the project logs event finished" + }, + "prompt_tokens": { + "type": "integer", + "nullable": true, + "description": "The number of tokens in the prompt used to generate the project logs event (only set if this is an LLM span)" + }, + "completion_tokens": { + "type": "integer", + "nullable": true, + "description": "The number of tokens in the completion generated by the model (only set if this is an LLM span)" + }, + "tokens": { + "type": "integer", + "nullable": true, + "description": "The total number of tokens in the input and output of the project logs event." + }, + "caller_functionname": { + "nullable": true, + "description": "This metric is deprecated" + }, + "caller_filename": { + "nullable": true, + "description": "This metric is deprecated" + }, + "caller_lineno": { + "nullable": true, + "description": "This metric is deprecated" + } + }, + "additionalProperties": { + "type": "number" + }, + "description": "Metrics are numerical measurements tracking the execution of the code that produced the project logs event. Use \"start\" and \"end\" to track the time span over which the project logs event was produced" + }, + "context": { + "type": "object", + "nullable": true, + "properties": { + "caller_functionname": { + "type": "string", + "nullable": true, + "description": "The function in code which created the project logs event" + }, + "caller_filename": { + "type": "string", + "nullable": true, + "description": "Name of the file in code where the project logs event was created" + }, + "caller_lineno": { + "type": "integer", + "nullable": true, + "description": "Line of code where the project logs event was created" + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "Context is additional information about the code that produced the project logs event. It is essentially the textual counterpart to `metrics`. Use the `caller_*` attributes to track the location in code which produced the project logs event" + }, + "span_attributes": { + "$ref": "#/components/schemas/SpanAttributes" + }, + "id": { + "type": "string", + "nullable": true, + "description": "A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "The timestamp the project logs event was created" + }, + "origin": { + "$ref": "#/components/schemas/ObjectReferenceNullish" + }, + "facets": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "string", + "nullable": true + }, + "description": "Facets for categorization (dictionary from facet id to value)" + }, + "_object_delete": { + "type": "boolean", + "nullable": true, + "description": "Pass `_object_delete=true` to mark the project logs event deleted. Deleted events will not show up in subsequent fetches for this project logs" + }, + "_is_merge": { + "type": "boolean", + "nullable": true, + "description": "The `_is_merge` field controls how the row is merged with any existing row with the same id in the DB. By default (or when set to `false`), the existing row is completely replaced by the new row. When set to `true`, the new row is deep-merged into the existing row, if one is found. If no existing row is found, the new row is inserted as is.\n\nFor example, say there is an existing row in the DB `{\"id\": \"foo\", \"input\": {\"a\": 5, \"b\": 10}}`. If we merge a new row as `{\"_is_merge\": true, \"id\": \"foo\", \"input\": {\"b\": 11, \"c\": 20}}`, the new row will be `{\"id\": \"foo\", \"input\": {\"a\": 5, \"b\": 11, \"c\": 20}}`. If we replace the new row as `{\"id\": \"foo\", \"input\": {\"b\": 11, \"c\": 20}}`, the new row will be `{\"id\": \"foo\", \"input\": {\"b\": 11, \"c\": 20}}`" + }, + "_merge_paths": { + "type": "array", + "nullable": true, + "items": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "The `_merge_paths` field allows controlling the depth of the merge, when `_is_merge=true`. `_merge_paths` is a list of paths, where each path is a list of field names. The deep merge will not descend below any of the specified merge paths.\n\nFor example, say there is an existing row in the DB `{\"id\": \"foo\", \"input\": {\"a\": {\"b\": 10}, \"c\": {\"d\": 20}}, \"output\": {\"a\": 20}}`. If we merge a new row as `{\"_is_merge\": true, \"_merge_paths\": [[\"input\", \"a\"], [\"output\"]], \"input\": {\"a\": {\"q\": 30}, \"c\": {\"e\": 30}, \"bar\": \"baz\"}, \"output\": {\"d\": 40}}`, the new row will be `{\"id\": \"foo\": \"input\": {\"a\": {\"q\": 30}, \"c\": {\"d\": 20, \"e\": 30}, \"bar\": \"baz\"}, \"output\": {\"d\": 40}}`. In this case, due to the merge paths, we have replaced `input.a` and `output`, but have still deep-merged `input` and `input.c`." + }, + "_array_delete": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "path": { + "type": "array", + "items": { + "type": "string" + } + }, + "delete": { + "type": "array", + "items": { + "nullable": true + } + } + }, + "required": [ + "path", + "delete" + ] + }, + "description": "The `_array_delete` field allows removing specific values from array fields. It is an array of objects with `path` and `delete` properties.\n\nFor example, to remove tags \"foo\" and \"bar\" from an existing row: `{\"_is_merge\": true, \"_array_delete\": [{\"path\": [\"tags\"], \"delete\": [\"foo\", \"bar\"]}]}`. For nested fields like `metadata.categories`, use `[{\"path\": [\"metadata\", \"categories\"], \"delete\": [\"value\"]}]`. This will remove those specific values from the array while preserving others." + }, + "_parent_id": { + "type": "string", + "nullable": true, + "description": "DEPRECATED: The `_parent_id` field is deprecated and should not be used. Support for `_parent_id` will be dropped in a future version of Braintrust. Log `span_id`, `root_span_id`, and `span_parents` explicitly instead.\n\nUse the `_parent_id` field to create this row as a subspan of an existing row. Tracking hierarchical relationships are important for tracing (see the [guide](https://www.braintrust.dev/docs/instrument) for full details).\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"_parent_id\": \"abc\", \"id\": \"llm_call\", \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + }, + "span_id": { + "type": "string", + "nullable": true, + "description": "Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details.\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"span_id\": \"span0\", \"root_span_id\": \"root_span0\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"id\": \"llm_call\", \"span_id\": \"span1\", \"root_span_id\": \"root_span0\", \"span_parents\": [\"span0\"], \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + }, + "root_span_id": { + "type": "string", + "nullable": true, + "description": "Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details.\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"span_id\": \"span0\", \"root_span_id\": \"root_span0\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"id\": \"llm_call\", \"span_id\": \"span1\", \"root_span_id\": \"root_span0\", \"span_parents\": [\"span0\"], \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + }, + "span_parents": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details.\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"span_id\": \"span0\", \"root_span_id\": \"root_span0\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"id\": \"llm_call\", \"span_id\": \"span1\", \"root_span_id\": \"root_span0\", \"span_parents\": [\"span0\"], \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + } + }, + "description": "A project logs event" + }, + "InsertProjectLogsEventRequest": { + "type": "object", + "properties": { + "events": { + "type": "array", + "items": { + "$ref": "#/components/schemas/InsertProjectLogsEvent" + }, + "description": "A list of project logs events to insert" + } + }, + "required": [ + "events" + ] + }, + "SavedFunctionId": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "function" + ] + }, + "id": { + "type": "string" + }, + "version": { + "type": "string", + "description": "The version of the function" + } + }, + "required": [ + "type", + "id" + ], + "title": "function" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "global" + ] + }, + "name": { + "type": "string" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + } + }, + "required": [ + "type", + "name" + ], + "title": "global" + }, + { + "type": "null" + } + ], + "description": "Optional function identifier that produced the classification" + }, + "ProjectLogsEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you" + }, + "_xact_id": { + "type": "string", + "description": "The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)" + }, + "_pagination_key": { + "type": "string", + "nullable": true, + "description": "A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore." + }, + "created": { + "type": "string", + "format": "date-time", + "description": "The timestamp the project logs event was created" + }, + "org_id": { + "type": "string", + "format": "uuid", + "description": "Unique id for the organization that the project belongs under" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project" + }, + "log_id": { + "type": "string", + "enum": [ + "g" + ], + "description": "A literal 'g' which identifies the log as a project log" + }, + "input": { + "nullable": true, + "description": "The arguments that uniquely define a user input (an arbitrary, JSON serializable object)." + }, + "output": { + "nullable": true, + "description": "The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question." + }, + "expected": { + "nullable": true, + "description": "The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models." + }, + "error": { + "nullable": true, + "description": "The error that occurred, if any." + }, + "scores": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "number", + "nullable": true, + "minimum": 0, + "maximum": 1 + }, + "description": "A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was covering similar concepts or not. You can use these scores to help you sort, filter, and compare logs." + }, + "metadata": { + "type": "object", + "nullable": true, + "properties": { + "model": { + "type": "string", + "nullable": true, + "description": "The model used for this example" + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags to log" + }, + "metrics": { + "type": "object", + "nullable": true, + "properties": { + "start": { + "type": "number", + "nullable": true, + "description": "A unix timestamp recording when the section of code which produced the project logs event started" + }, + "end": { + "type": "number", + "nullable": true, + "description": "A unix timestamp recording when the section of code which produced the project logs event finished" + }, + "prompt_tokens": { + "type": "integer", + "nullable": true, + "description": "The number of tokens in the prompt used to generate the project logs event (only set if this is an LLM span)" + }, + "completion_tokens": { + "type": "integer", + "nullable": true, + "description": "The number of tokens in the completion generated by the model (only set if this is an LLM span)" + }, + "tokens": { + "type": "integer", + "nullable": true, + "description": "The total number of tokens in the input and output of the project logs event." + }, + "caller_functionname": { + "nullable": true, + "description": "This metric is deprecated" + }, + "caller_filename": { + "nullable": true, + "description": "This metric is deprecated" + }, + "caller_lineno": { + "nullable": true, + "description": "This metric is deprecated" + } + }, + "additionalProperties": { + "type": "number" + }, + "description": "Metrics are numerical measurements tracking the execution of the code that produced the project logs event. Use \"start\" and \"end\" to track the time span over which the project logs event was produced" + }, + "context": { + "type": "object", + "nullable": true, + "properties": { + "caller_functionname": { + "type": "string", + "nullable": true, + "description": "The function in code which created the project logs event" + }, + "caller_filename": { + "type": "string", + "nullable": true, + "description": "Name of the file in code where the project logs event was created" + }, + "caller_lineno": { + "type": "integer", + "nullable": true, + "description": "Line of code where the project logs event was created" + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "Context is additional information about the code that produced the project logs event. It is essentially the textual counterpart to `metrics`. Use the `caller_*` attributes to track the location in code which produced the project logs event" + }, + "span_id": { + "type": "string", + "description": "A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing" + }, + "span_parents": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "An array of the parent `span_ids` of this project logs event. This should be empty for the root span of a trace, and should most often contain just one parent element for subspans" + }, + "root_span_id": { + "type": "string", + "description": "A unique identifier for the trace this project logs event belongs to" + }, + "is_root": { + "type": "boolean", + "nullable": true, + "description": "Whether this span is a root span" + }, + "span_attributes": { + "$ref": "#/components/schemas/SpanAttributes" + }, + "origin": { + "$ref": "#/components/schemas/ObjectReferenceNullish" + }, + "comments": { + "type": "array", + "nullable": true, + "items": { + "nullable": true + }, + "description": "Optional list of comments attached to this event" + }, + "audit_data": { + "type": "array", + "nullable": true, + "items": { + "nullable": true + }, + "description": "Optional list of audit entries attached to this event" + }, + "_async_scoring_state": { + "nullable": true, + "description": "The async scoring state for this event" + }, + "facets": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "string", + "nullable": true + }, + "description": "Facets for categorization (dictionary from facet id to value)" + }, + "classifications": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Stable classification identifier" + }, + "label": { + "type": "string", + "description": "Original label of the classification item, which is useful for search and indexing purposes" + }, + "confidence": { + "type": "number", + "nullable": true, + "description": "Optional confidence score for the classification" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Optional metadata associated with the classification" + }, + "source": { + "$ref": "#/components/schemas/SavedFunctionId" + } + }, + "required": [ + "id" + ] + } + }, + "description": "Classifications for this event (dictionary from classification name to items)" + } + }, + "required": [ + "id", + "_xact_id", + "created", + "org_id", + "project_id", + "log_id", + "span_id", + "root_span_id" + ] + }, + "FetchProjectLogsEventsResponse": { + "type": "object", + "properties": { + "events": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectLogsEvent" + }, + "description": "A list of fetched events" + }, + "cursor": { + "type": "string", + "nullable": true, + "description": "Pagination cursor\n\nPass this string directly as the `cursor` param to your next fetch request to get the next page of results. Not provided if the returned result set is empty." + } + }, + "required": [ + "events" + ] + }, + "FetchLimit": { + "type": "integer", + "nullable": true, + "minimum": 0, + "description": "limit the number of traces fetched\n\nFetch queries may be paginated if the total result size is expected to be large (e.g. project_logs which accumulate over a long time). Note that fetch queries only support pagination in descending time order (from latest to earliest `_xact_id`. Furthermore, later pages may return rows which showed up in earlier pages, except with an earlier `_xact_id`. This happens because pagination occurs over the whole version history of the event log. You will most likely want to exclude any such duplicate, outdated rows (by `id`) from your combined result set.\n\nThe `limit` parameter controls the number of full traces to return. So you may end up with more individual rows than the specified limit if you are fetching events containing traces." + }, + "FetchPaginationCursor": { + "type": "string", + "nullable": true, + "description": "An opaque string to be used as a cursor for the next page of results, in order from latest to earliest.\n\nThe string can be obtained directly from the `cursor` property of the previous fetch query" + }, + "FetchEventsRequest": { + "type": "object", + "properties": { + "limit": { + "$ref": "#/components/schemas/FetchLimit" + }, + "cursor": { + "$ref": "#/components/schemas/FetchPaginationCursor" + }, + "max_xact_id": { + "$ref": "#/components/schemas/MaxXactId", + "nullable": true + }, + "max_root_span_id": { + "$ref": "#/components/schemas/MaxRootSpanId", + "nullable": true + }, + "version": { + "$ref": "#/components/schemas/Version", + "nullable": true + } + } + }, + "FeedbackResponseSchema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ] + } + }, + "required": [ + "status" + ] + }, + "FeedbackProjectLogsItem": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The id of the project logs event to log feedback for. This is the row `id` returned by `POST /v1/project_logs/{project_id}/insert`" + }, + "scores": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "number", + "nullable": true, + "minimum": 0, + "maximum": 1 + }, + "description": "A dictionary of numeric values (between 0 and 1) to log. These scores will be merged into the existing scores for the project logs event" + }, + "expected": { + "nullable": true, + "description": "The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not" + }, + "comment": { + "type": "string", + "nullable": true, + "description": "An optional comment string to log about the project logs event" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "A dictionary with additional data about the feedback. If you have a `user_id`, you can log it here and access it in the Braintrust UI. Note, this metadata does not correspond to the main event itself, but rather the audit log attached to the event." + }, + "source": { + "type": "string", + "nullable": true, + "enum": [ + "app", + "api", + "external", + null + ], + "description": "The source of the feedback. Must be one of \"external\" (default), \"app\", or \"api\"" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags to log" + } + }, + "required": [ + "id" + ] + }, + "FeedbackProjectLogsEventRequest": { + "type": "object", + "properties": { + "feedback": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FeedbackProjectLogsItem" + }, + "description": "A list of project logs feedback items" + } + }, + "required": [ + "feedback" + ] + }, + "RepoInfo": { + "type": "object", + "nullable": true, + "properties": { + "commit": { + "type": "string", + "nullable": true, + "description": "SHA of most recent commit" + }, + "branch": { + "type": "string", + "nullable": true, + "description": "Name of the branch the most recent commit belongs to" + }, + "tag": { + "type": "string", + "nullable": true, + "description": "Name of the tag on the most recent commit" + }, + "dirty": { + "type": "boolean", + "nullable": true, + "description": "Whether or not the repo had uncommitted changes when snapshotted" + }, + "author_name": { + "type": "string", + "nullable": true, + "description": "Name of the author of the most recent commit" + }, + "author_email": { + "type": "string", + "nullable": true, + "description": "Email of the author of the most recent commit" + }, + "commit_message": { + "type": "string", + "nullable": true, + "description": "Most recent commit message" + }, + "commit_time": { + "type": "string", + "nullable": true, + "description": "Time of the most recent commit" + }, + "git_diff": { + "type": "string", + "nullable": true, + "description": "If the repo was dirty when run, this includes the diff between the current state of the repo and the most recent commit." + } + }, + "description": "Metadata about the state of the repo when the experiment was created" + }, + "Experiment": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the experiment" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the experiment belongs under" + }, + "name": { + "type": "string", + "description": "Name of the experiment. Within a project, experiment names are unique" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the experiment" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of experiment creation" + }, + "repo_info": { + "$ref": "#/components/schemas/RepoInfo" + }, + "commit": { + "type": "string", + "nullable": true, + "description": "Commit, taken directly from `repo_info.commit`" + }, + "base_exp_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Id of default base experiment to compare against when viewing this experiment" + }, + "deleted_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of experiment deletion, or null if the experiment is still active" + }, + "dataset_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifier of the linked dataset, or null if the experiment is not linked to a dataset" + }, + "dataset_version": { + "type": "string", + "nullable": true, + "description": "Version number of the linked dataset the experiment was run against. This can be used to reproduce the experiment after the dataset has been modified." + }, + "internal_metadata": { + "type": "object", + "nullable": true, + "properties": { + "dataset_filter": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "BTQL filter payload used to evaluate a subset of a linked dataset." + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "Braintrust-controlled metadata about the experiment." + }, + "parameters_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifier of the linked saved parameters object, or null if the experiment is not linked to saved parameters" + }, + "parameters_version": { + "type": "string", + "nullable": true, + "description": "Version number of the linked saved parameters object the experiment was run against." + }, + "public": { + "type": "boolean", + "description": "Whether or not the experiment is public. Public experiments can be viewed by anybody inside or outside the organization" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifies the user who created the experiment" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "User-controlled metadata about the experiment" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the experiment" + } + }, + "required": [ + "id", + "project_id", + "name", + "public" + ] + }, + "CreateExperiment": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the experiment belongs under" + }, + "name": { + "type": "string", + "nullable": true, + "minLength": 1, + "description": "Name of the experiment. Within a project, experiment names are unique" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the experiment" + }, + "repo_info": { + "$ref": "#/components/schemas/RepoInfo" + }, + "base_exp_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Id of default base experiment to compare against when viewing this experiment" + }, + "dataset_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifier of the linked dataset, or null if the experiment is not linked to a dataset" + }, + "dataset_version": { + "type": "string", + "nullable": true, + "description": "Version number of the linked dataset the experiment was run against. This can be used to reproduce the experiment after the dataset has been modified." + }, + "internal_metadata": { + "type": "object", + "nullable": true, + "properties": { + "dataset_filter": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "BTQL filter payload used to evaluate a subset of a linked dataset." + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "Braintrust-controlled metadata about the experiment." + }, + "parameters_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifier of the linked saved parameters object, or null if the experiment is not linked to saved parameters" + }, + "parameters_version": { + "type": "string", + "nullable": true, + "description": "Version number of the linked saved parameters object the experiment was run against." + }, + "public": { + "type": "boolean", + "nullable": true, + "description": "Whether or not the experiment is public. Public experiments can be viewed by anybody inside or outside the organization" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "User-controlled metadata about the experiment" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the experiment" + }, + "ensure_new": { + "type": "boolean", + "nullable": true, + "description": "Normally, creating an experiment with the same name as an existing experiment will return the existing one un-modified. But if `ensure_new` is true, registration will generate a new experiment with a unique name in case of a conflict." + } + }, + "required": [ + "project_id" + ] + }, + "PatchExperiment": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the experiment. Within a project, experiment names are unique" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the experiment" + }, + "repo_info": { + "$ref": "#/components/schemas/RepoInfo" + }, + "base_exp_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Id of default base experiment to compare against when viewing this experiment" + }, + "dataset_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifier of the linked dataset, or null if the experiment is not linked to a dataset" + }, + "dataset_version": { + "type": "string", + "nullable": true, + "description": "Version number of the linked dataset the experiment was run against. This can be used to reproduce the experiment after the dataset has been modified." + }, + "internal_metadata": { + "type": "object", + "nullable": true, + "properties": { + "dataset_filter": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "BTQL filter payload used to evaluate a subset of a linked dataset." + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "Braintrust-controlled metadata about the experiment." + }, + "parameters_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifier of the linked saved parameters object, or null if the experiment is not linked to saved parameters" + }, + "parameters_version": { + "type": "string", + "nullable": true, + "description": "Version number of the linked saved parameters object the experiment was run against." + }, + "public": { + "type": "boolean", + "nullable": true, + "description": "Whether or not the experiment is public. Public experiments can be viewed by anybody inside or outside the organization" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "User-controlled metadata about the experiment" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the experiment" + } + } + }, + "InsertExperimentEvent": { + "type": "object", + "properties": { + "input": { + "nullable": true, + "description": "The arguments that uniquely define a test case (an arbitrary, JSON serializable object). Later on, Braintrust will use the `input` to know whether two test cases are the same between experiments, so they should not contain experiment-specific state. A simple rule of thumb is that if you run the same experiment twice, the `input` should be identical" + }, + "output": { + "nullable": true, + "description": "The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question" + }, + "expected": { + "nullable": true, + "description": "The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate your experiments while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models" + }, + "error": { + "nullable": true, + "description": "The error that occurred, if any." + }, + "scores": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "number", + "nullable": true, + "minimum": 0, + "maximum": 1 + }, + "description": "A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was covering similar concepts or not. You can use these scores to help you sort, filter, and compare experiments" + }, + "metadata": { + "type": "object", + "nullable": true, + "properties": { + "model": { + "type": "string", + "nullable": true, + "description": "The model used for this example" + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags to log" + }, + "metrics": { + "type": "object", + "nullable": true, + "properties": { + "start": { + "type": "number", + "nullable": true, + "description": "A unix timestamp recording when the section of code which produced the experiment event started" + }, + "end": { + "type": "number", + "nullable": true, + "description": "A unix timestamp recording when the section of code which produced the experiment event finished" + }, + "prompt_tokens": { + "type": "integer", + "nullable": true, + "description": "The number of tokens in the prompt used to generate the experiment event (only set if this is an LLM span)" + }, + "completion_tokens": { + "type": "integer", + "nullable": true, + "description": "The number of tokens in the completion generated by the model (only set if this is an LLM span)" + }, + "tokens": { + "type": "integer", + "nullable": true, + "description": "The total number of tokens in the input and output of the experiment event." + }, + "caller_functionname": { + "nullable": true, + "description": "This metric is deprecated" + }, + "caller_filename": { + "nullable": true, + "description": "This metric is deprecated" + }, + "caller_lineno": { + "nullable": true, + "description": "This metric is deprecated" + } + }, + "additionalProperties": { + "type": "number" + }, + "description": "Metrics are numerical measurements tracking the execution of the code that produced the experiment event. Use \"start\" and \"end\" to track the time span over which the experiment event was produced" + }, + "context": { + "type": "object", + "nullable": true, + "properties": { + "caller_functionname": { + "type": "string", + "nullable": true, + "description": "The function in code which created the experiment event" + }, + "caller_filename": { + "type": "string", + "nullable": true, + "description": "Name of the file in code where the experiment event was created" + }, + "caller_lineno": { + "type": "integer", + "nullable": true, + "description": "Line of code where the experiment event was created" + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "Context is additional information about the code that produced the experiment event. It is essentially the textual counterpart to `metrics`. Use the `caller_*` attributes to track the location in code which produced the experiment event" + }, + "span_attributes": { + "$ref": "#/components/schemas/SpanAttributes" + }, + "id": { + "type": "string", + "nullable": true, + "description": "A unique identifier for the experiment event. If you don't provide one, Braintrust will generate one for you" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "The timestamp the experiment event was created" + }, + "origin": { + "$ref": "#/components/schemas/ObjectReferenceNullish" + }, + "facets": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "string", + "nullable": true + }, + "description": "Facets for categorization (dictionary from facet id to value)" + }, + "_object_delete": { + "type": "boolean", + "nullable": true, + "description": "Pass `_object_delete=true` to mark the experiment event deleted. Deleted events will not show up in subsequent fetches for this experiment" + }, + "_is_merge": { + "type": "boolean", + "nullable": true, + "description": "The `_is_merge` field controls how the row is merged with any existing row with the same id in the DB. By default (or when set to `false`), the existing row is completely replaced by the new row. When set to `true`, the new row is deep-merged into the existing row, if one is found. If no existing row is found, the new row is inserted as is.\n\nFor example, say there is an existing row in the DB `{\"id\": \"foo\", \"input\": {\"a\": 5, \"b\": 10}}`. If we merge a new row as `{\"_is_merge\": true, \"id\": \"foo\", \"input\": {\"b\": 11, \"c\": 20}}`, the new row will be `{\"id\": \"foo\", \"input\": {\"a\": 5, \"b\": 11, \"c\": 20}}`. If we replace the new row as `{\"id\": \"foo\", \"input\": {\"b\": 11, \"c\": 20}}`, the new row will be `{\"id\": \"foo\", \"input\": {\"b\": 11, \"c\": 20}}`" + }, + "_merge_paths": { + "type": "array", + "nullable": true, + "items": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "The `_merge_paths` field allows controlling the depth of the merge, when `_is_merge=true`. `_merge_paths` is a list of paths, where each path is a list of field names. The deep merge will not descend below any of the specified merge paths.\n\nFor example, say there is an existing row in the DB `{\"id\": \"foo\", \"input\": {\"a\": {\"b\": 10}, \"c\": {\"d\": 20}}, \"output\": {\"a\": 20}}`. If we merge a new row as `{\"_is_merge\": true, \"_merge_paths\": [[\"input\", \"a\"], [\"output\"]], \"input\": {\"a\": {\"q\": 30}, \"c\": {\"e\": 30}, \"bar\": \"baz\"}, \"output\": {\"d\": 40}}`, the new row will be `{\"id\": \"foo\": \"input\": {\"a\": {\"q\": 30}, \"c\": {\"d\": 20, \"e\": 30}, \"bar\": \"baz\"}, \"output\": {\"d\": 40}}`. In this case, due to the merge paths, we have replaced `input.a` and `output`, but have still deep-merged `input` and `input.c`." + }, + "_array_delete": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "path": { + "type": "array", + "items": { + "type": "string" + } + }, + "delete": { + "type": "array", + "items": { + "nullable": true + } + } + }, + "required": [ + "path", + "delete" + ] + }, + "description": "The `_array_delete` field allows removing specific values from array fields. It is an array of objects with `path` and `delete` properties.\n\nFor example, to remove tags \"foo\" and \"bar\" from an existing row: `{\"_is_merge\": true, \"_array_delete\": [{\"path\": [\"tags\"], \"delete\": [\"foo\", \"bar\"]}]}`. For nested fields like `metadata.categories`, use `[{\"path\": [\"metadata\", \"categories\"], \"delete\": [\"value\"]}]`. This will remove those specific values from the array while preserving others." + }, + "_parent_id": { + "type": "string", + "nullable": true, + "description": "DEPRECATED: The `_parent_id` field is deprecated and should not be used. Support for `_parent_id` will be dropped in a future version of Braintrust. Log `span_id`, `root_span_id`, and `span_parents` explicitly instead.\n\nUse the `_parent_id` field to create this row as a subspan of an existing row. Tracking hierarchical relationships are important for tracing (see the [guide](https://www.braintrust.dev/docs/instrument) for full details).\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"_parent_id\": \"abc\", \"id\": \"llm_call\", \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + }, + "span_id": { + "type": "string", + "nullable": true, + "description": "Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details.\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"span_id\": \"span0\", \"root_span_id\": \"root_span0\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"id\": \"llm_call\", \"span_id\": \"span1\", \"root_span_id\": \"root_span0\", \"span_parents\": [\"span0\"], \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + }, + "root_span_id": { + "type": "string", + "nullable": true, + "description": "Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details.\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"span_id\": \"span0\", \"root_span_id\": \"root_span0\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"id\": \"llm_call\", \"span_id\": \"span1\", \"root_span_id\": \"root_span0\", \"span_parents\": [\"span0\"], \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + }, + "span_parents": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details.\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"span_id\": \"span0\", \"root_span_id\": \"root_span0\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"id\": \"llm_call\", \"span_id\": \"span1\", \"root_span_id\": \"root_span0\", \"span_parents\": [\"span0\"], \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + } + }, + "description": "An experiment event" + }, + "InsertExperimentEventRequest": { + "type": "object", + "properties": { + "events": { + "type": "array", + "items": { + "$ref": "#/components/schemas/InsertExperimentEvent" + }, + "description": "A list of experiment events to insert" + } + }, + "required": [ + "events" + ] + }, + "ExperimentEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "A unique identifier for the experiment event. If you don't provide one, Braintrust will generate one for you" + }, + "_xact_id": { + "type": "string", + "description": "The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the experiment (see the `version` parameter)" + }, + "created": { + "type": "string", + "format": "date-time", + "description": "The timestamp the experiment event was created" + }, + "_pagination_key": { + "type": "string", + "nullable": true, + "description": "A stable, time-ordered key that can be used to paginate over experiment events. This field is auto-generated by Braintrust and only exists in Brainstore." + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the experiment belongs under" + }, + "experiment_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the experiment" + }, + "input": { + "nullable": true, + "description": "The arguments that uniquely define a test case (an arbitrary, JSON serializable object). Later on, Braintrust will use the `input` to know whether two test cases are the same between experiments, so they should not contain experiment-specific state. A simple rule of thumb is that if you run the same experiment twice, the `input` should be identical" + }, + "output": { + "nullable": true, + "description": "The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question" + }, + "expected": { + "nullable": true, + "description": "The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate your experiments while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models" + }, + "error": { + "nullable": true, + "description": "The error that occurred, if any." + }, + "scores": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "number", + "nullable": true, + "minimum": 0, + "maximum": 1 + }, + "description": "A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was covering similar concepts or not. You can use these scores to help you sort, filter, and compare experiments" + }, + "metadata": { + "type": "object", + "nullable": true, + "properties": { + "model": { + "type": "string", + "nullable": true, + "description": "The model used for this example" + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags to log" + }, + "metrics": { + "type": "object", + "nullable": true, + "properties": { + "start": { + "type": "number", + "nullable": true, + "description": "A unix timestamp recording when the section of code which produced the experiment event started" + }, + "end": { + "type": "number", + "nullable": true, + "description": "A unix timestamp recording when the section of code which produced the experiment event finished" + }, + "prompt_tokens": { + "type": "integer", + "nullable": true, + "description": "The number of tokens in the prompt used to generate the experiment event (only set if this is an LLM span)" + }, + "completion_tokens": { + "type": "integer", + "nullable": true, + "description": "The number of tokens in the completion generated by the model (only set if this is an LLM span)" + }, + "tokens": { + "type": "integer", + "nullable": true, + "description": "The total number of tokens in the input and output of the experiment event." + }, + "caller_functionname": { + "nullable": true, + "description": "This metric is deprecated" + }, + "caller_filename": { + "nullable": true, + "description": "This metric is deprecated" + }, + "caller_lineno": { + "nullable": true, + "description": "This metric is deprecated" + } + }, + "additionalProperties": { + "type": "number" + }, + "description": "Metrics are numerical measurements tracking the execution of the code that produced the experiment event. Use \"start\" and \"end\" to track the time span over which the experiment event was produced" + }, + "context": { + "type": "object", + "nullable": true, + "properties": { + "caller_functionname": { + "type": "string", + "nullable": true, + "description": "The function in code which created the experiment event" + }, + "caller_filename": { + "type": "string", + "nullable": true, + "description": "Name of the file in code where the experiment event was created" + }, + "caller_lineno": { + "type": "integer", + "nullable": true, + "description": "Line of code where the experiment event was created" + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "Context is additional information about the code that produced the experiment event. It is essentially the textual counterpart to `metrics`. Use the `caller_*` attributes to track the location in code which produced the experiment event" + }, + "span_id": { + "type": "string", + "description": "A unique identifier used to link different experiment events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing" + }, + "span_parents": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "An array of the parent `span_ids` of this experiment event. This should be empty for the root span of a trace, and should most often contain just one parent element for subspans" + }, + "root_span_id": { + "type": "string", + "description": "A unique identifier for the trace this experiment event belongs to" + }, + "span_attributes": { + "$ref": "#/components/schemas/SpanAttributes" + }, + "is_root": { + "type": "boolean", + "nullable": true, + "description": "Whether this span is a root span" + }, + "origin": { + "$ref": "#/components/schemas/ObjectReferenceNullish" + }, + "comments": { + "type": "array", + "nullable": true, + "items": { + "nullable": true + }, + "description": "Optional list of comments attached to this event" + }, + "audit_data": { + "type": "array", + "nullable": true, + "items": { + "nullable": true + }, + "description": "Optional list of audit entries attached to this event" + }, + "facets": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "string", + "nullable": true + }, + "description": "Facets for categorization (dictionary from facet id to value)" + }, + "classifications": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Stable classification identifier" + }, + "label": { + "type": "string", + "description": "Original label of the classification item, which is useful for search and indexing purposes" + }, + "confidence": { + "type": "number", + "nullable": true, + "description": "Optional confidence score for the classification" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Optional metadata associated with the classification" + }, + "source": { + "$ref": "#/components/schemas/SavedFunctionId" + } + }, + "required": [ + "id" + ] + } + }, + "description": "Classifications for this event (dictionary from classification name to items)" + } + }, + "required": [ + "id", + "_xact_id", + "created", + "project_id", + "experiment_id", + "span_id", + "root_span_id" + ] + }, + "FetchExperimentEventsResponse": { + "type": "object", + "properties": { + "events": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExperimentEvent" + }, + "description": "A list of fetched events" + }, + "cursor": { + "type": "string", + "nullable": true, + "description": "Pagination cursor\n\nPass this string directly as the `cursor` param to your next fetch request to get the next page of results. Not provided if the returned result set is empty." + } + }, + "required": [ + "events" + ] + }, + "FeedbackExperimentItem": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The id of the experiment event to log feedback for. This is the row `id` returned by `POST /v1/experiment/{experiment_id}/insert`" + }, + "scores": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "number", + "nullable": true, + "minimum": 0, + "maximum": 1 + }, + "description": "A dictionary of numeric values (between 0 and 1) to log. These scores will be merged into the existing scores for the experiment event" + }, + "expected": { + "nullable": true, + "description": "The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not" + }, + "comment": { + "type": "string", + "nullable": true, + "description": "An optional comment string to log about the experiment event" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "A dictionary with additional data about the feedback. If you have a `user_id`, you can log it here and access it in the Braintrust UI. Note, this metadata does not correspond to the main event itself, but rather the audit log attached to the event." + }, + "source": { + "type": "string", + "nullable": true, + "enum": [ + "app", + "api", + "external", + null + ], + "description": "The source of the feedback. Must be one of \"external\" (default), \"app\", or \"api\"" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags to log" + } + }, + "required": [ + "id" + ] + }, + "FeedbackExperimentEventRequest": { + "type": "object", + "properties": { + "feedback": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FeedbackExperimentItem" + }, + "description": "A list of experiment feedback items" + } + }, + "required": [ + "feedback" + ] + }, + "ScoreSummary": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the score" + }, + "score": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Average score across all examples" + }, + "diff": { + "type": "number", + "minimum": -1, + "maximum": 1, + "description": "Difference in score between the current and comparison experiment" + }, + "improvements": { + "type": "integer", + "minimum": 0, + "description": "Number of improvements in the score" + }, + "regressions": { + "type": "integer", + "minimum": 0, + "description": "Number of regressions in the score" + } + }, + "required": [ + "name", + "score", + "improvements", + "regressions" + ], + "description": "Summary of a score's performance" + }, + "MetricSummary": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the metric" + }, + "metric": { + "type": "number", + "description": "Average metric across all examples" + }, + "unit": { + "type": "string", + "description": "Unit label for the metric" + }, + "diff": { + "type": "number", + "description": "Difference in metric between the current and comparison experiment" + }, + "improvements": { + "type": "integer", + "minimum": 0, + "description": "Number of improvements in the metric" + }, + "regressions": { + "type": "integer", + "minimum": 0, + "description": "Number of regressions in the metric" + } + }, + "required": [ + "name", + "metric", + "unit", + "improvements", + "regressions" + ], + "description": "Summary of a metric's performance" + }, + "SummarizeExperimentResponse": { + "type": "object", + "properties": { + "project_name": { + "type": "string", + "description": "Name of the project that the experiment belongs to" + }, + "experiment_name": { + "type": "string", + "description": "Name of the experiment" + }, + "project_url": { + "type": "string", + "format": "uri", + "description": "URL to the project's page in the Braintrust app" + }, + "experiment_url": { + "type": "string", + "format": "uri", + "description": "URL to the experiment's page in the Braintrust app" + }, + "comparison_experiment_name": { + "type": "string", + "nullable": true, + "description": "The experiment which scores are baselined against" + }, + "scores": { + "type": "object", + "nullable": true, + "additionalProperties": { + "$ref": "#/components/schemas/ScoreSummary" + }, + "description": "Summary of the experiment's scores" + }, + "metrics": { + "type": "object", + "nullable": true, + "additionalProperties": { + "$ref": "#/components/schemas/MetricSummary" + }, + "description": "Summary of the experiment's metrics" + } + }, + "required": [ + "project_name", + "experiment_name", + "project_url", + "experiment_url" + ], + "description": "Summary of an experiment" + }, + "Dataset": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the dataset" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the dataset belongs under" + }, + "name": { + "type": "string", + "description": "Name of the dataset. Within a project, dataset names are unique" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the dataset" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of dataset creation" + }, + "deleted_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of dataset deletion, or null if the dataset is still active" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifies the user who created the dataset" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the dataset" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "User-controlled metadata about the dataset" + }, + "url_slug": { + "type": "string", + "description": "URL slug for the dataset. used to construct dataset URLs" + } + }, + "required": [ + "id", + "project_id", + "name", + "url_slug" + ] + }, + "CreateDataset": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the dataset belongs under" + }, + "name": { + "type": "string", + "minLength": 1, + "description": "Name of the dataset. Within a project, dataset names are unique" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the dataset" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the dataset" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "User-controlled metadata about the dataset" + } + }, + "required": [ + "project_id", + "name" + ] + }, + "PatchDataset": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the dataset. Within a project, dataset names are unique" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the dataset" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the dataset" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "User-controlled metadata about the dataset" + } + } + }, + "InsertDatasetEvent": { + "type": "object", + "properties": { + "input": { + "nullable": true, + "description": "The argument that uniquely define an input case (an arbitrary, JSON serializable object)" + }, + "expected": { + "nullable": true, + "description": "The output of your application, including post-processing (an arbitrary, JSON serializable object)" + }, + "metadata": { + "type": "object", + "nullable": true, + "properties": { + "model": { + "type": "string", + "nullable": true, + "description": "The model used for this example" + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags to log" + }, + "id": { + "type": "string", + "nullable": true, + "description": "A unique identifier for the dataset event. If you don't provide one, Braintrust will generate one for you" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "The timestamp the dataset event was created" + }, + "origin": { + "$ref": "#/components/schemas/ObjectReferenceNullish" + }, + "facets": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "string", + "nullable": true + }, + "description": "Facets for categorization (dictionary from facet id to value)" + }, + "_object_delete": { + "type": "boolean", + "nullable": true, + "description": "Pass `_object_delete=true` to mark the dataset event deleted. Deleted events will not show up in subsequent fetches for this dataset" + }, + "_is_merge": { + "type": "boolean", + "nullable": true, + "description": "The `_is_merge` field controls how the row is merged with any existing row with the same id in the DB. By default (or when set to `false`), the existing row is completely replaced by the new row. When set to `true`, the new row is deep-merged into the existing row, if one is found. If no existing row is found, the new row is inserted as is.\n\nFor example, say there is an existing row in the DB `{\"id\": \"foo\", \"input\": {\"a\": 5, \"b\": 10}}`. If we merge a new row as `{\"_is_merge\": true, \"id\": \"foo\", \"input\": {\"b\": 11, \"c\": 20}}`, the new row will be `{\"id\": \"foo\", \"input\": {\"a\": 5, \"b\": 11, \"c\": 20}}`. If we replace the new row as `{\"id\": \"foo\", \"input\": {\"b\": 11, \"c\": 20}}`, the new row will be `{\"id\": \"foo\", \"input\": {\"b\": 11, \"c\": 20}}`" + }, + "_merge_paths": { + "type": "array", + "nullable": true, + "items": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "The `_merge_paths` field allows controlling the depth of the merge, when `_is_merge=true`. `_merge_paths` is a list of paths, where each path is a list of field names. The deep merge will not descend below any of the specified merge paths.\n\nFor example, say there is an existing row in the DB `{\"id\": \"foo\", \"input\": {\"a\": {\"b\": 10}, \"c\": {\"d\": 20}}, \"output\": {\"a\": 20}}`. If we merge a new row as `{\"_is_merge\": true, \"_merge_paths\": [[\"input\", \"a\"], [\"output\"]], \"input\": {\"a\": {\"q\": 30}, \"c\": {\"e\": 30}, \"bar\": \"baz\"}, \"output\": {\"d\": 40}}`, the new row will be `{\"id\": \"foo\": \"input\": {\"a\": {\"q\": 30}, \"c\": {\"d\": 20, \"e\": 30}, \"bar\": \"baz\"}, \"output\": {\"d\": 40}}`. In this case, due to the merge paths, we have replaced `input.a` and `output`, but have still deep-merged `input` and `input.c`." + }, + "_array_delete": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "path": { + "type": "array", + "items": { + "type": "string" + } + }, + "delete": { + "type": "array", + "items": { + "nullable": true + } + } + }, + "required": [ + "path", + "delete" + ] + }, + "description": "The `_array_delete` field allows removing specific values from array fields. It is an array of objects with `path` and `delete` properties.\n\nFor example, to remove tags \"foo\" and \"bar\" from an existing row: `{\"_is_merge\": true, \"_array_delete\": [{\"path\": [\"tags\"], \"delete\": [\"foo\", \"bar\"]}]}`. For nested fields like `metadata.categories`, use `[{\"path\": [\"metadata\", \"categories\"], \"delete\": [\"value\"]}]`. This will remove those specific values from the array while preserving others." + }, + "_parent_id": { + "type": "string", + "nullable": true, + "description": "DEPRECATED: The `_parent_id` field is deprecated and should not be used. Support for `_parent_id` will be dropped in a future version of Braintrust. Log `span_id`, `root_span_id`, and `span_parents` explicitly instead.\n\nUse the `_parent_id` field to create this row as a subspan of an existing row. Tracking hierarchical relationships are important for tracing (see the [guide](https://www.braintrust.dev/docs/instrument) for full details).\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"_parent_id\": \"abc\", \"id\": \"llm_call\", \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + }, + "span_id": { + "type": "string", + "nullable": true, + "description": "Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details.\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"span_id\": \"span0\", \"root_span_id\": \"root_span0\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"id\": \"llm_call\", \"span_id\": \"span1\", \"root_span_id\": \"root_span0\", \"span_parents\": [\"span0\"], \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + }, + "root_span_id": { + "type": "string", + "nullable": true, + "description": "Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details.\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"span_id\": \"span0\", \"root_span_id\": \"root_span0\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"id\": \"llm_call\", \"span_id\": \"span1\", \"root_span_id\": \"root_span0\", \"span_parents\": [\"span0\"], \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + }, + "span_parents": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details.\n\nFor example, say we have logged a row `{\"id\": \"abc\", \"span_id\": \"span0\", \"root_span_id\": \"root_span0\", \"input\": \"foo\", \"output\": \"bar\", \"expected\": \"boo\", \"scores\": {\"correctness\": 0.33}}`. We can create a sub-span of the parent row by logging `{\"id\": \"llm_call\", \"span_id\": \"span1\", \"root_span_id\": \"root_span0\", \"span_parents\": [\"span0\"], \"input\": {\"prompt\": \"What comes after foo?\"}, \"output\": \"bar\", \"metrics\": {\"tokens\": 1}}`. In the webapp, only the root span row `\"abc\"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `\"llm_call\"` row) by clicking on the \"abc\" row.\n\nIf the row is being merged into an existing row, this field will be ignored." + } + }, + "description": "A dataset event" + }, + "InsertDatasetEventRequest": { + "type": "object", + "properties": { + "events": { + "type": "array", + "items": { + "$ref": "#/components/schemas/InsertDatasetEvent" + }, + "description": "A list of dataset events to insert" + } + }, + "required": [ + "events" + ] + }, + "DatasetEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "A unique identifier for the dataset event. If you don't provide one, Braintrust will generate one for you" + }, + "_xact_id": { + "type": "string", + "description": "The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the dataset (see the `version` parameter)" + }, + "created": { + "type": "string", + "format": "date-time", + "description": "The timestamp the dataset event was created" + }, + "_pagination_key": { + "type": "string", + "nullable": true, + "description": "A stable, time-ordered key that can be used to paginate over dataset events. This field is auto-generated by Braintrust and only exists in Brainstore." + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the dataset belongs under" + }, + "dataset_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the dataset" + }, + "input": { + "nullable": true, + "description": "The argument that uniquely define an input case (an arbitrary, JSON serializable object)" + }, + "expected": { + "nullable": true, + "description": "The output of your application, including post-processing (an arbitrary, JSON serializable object)" + }, + "metadata": { + "type": "object", + "nullable": true, + "properties": { + "model": { + "type": "string", + "nullable": true, + "description": "The model used for this example" + } + }, + "additionalProperties": { + "nullable": true + }, + "description": "A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags to log" + }, + "span_id": { + "type": "string", + "description": "A unique identifier used to link different dataset events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing" + }, + "root_span_id": { + "type": "string", + "description": "A unique identifier for the trace this dataset event belongs to" + }, + "is_root": { + "type": "boolean", + "nullable": true, + "description": "Whether this span is a root span" + }, + "origin": { + "$ref": "#/components/schemas/ObjectReferenceNullish" + }, + "comments": { + "type": "array", + "nullable": true, + "items": { + "nullable": true + }, + "description": "Optional list of comments attached to this event" + }, + "audit_data": { + "type": "array", + "nullable": true, + "items": { + "nullable": true + }, + "description": "Optional list of audit entries attached to this event" + }, + "facets": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "string", + "nullable": true + }, + "description": "Facets for categorization (dictionary from facet id to value)" + }, + "classifications": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Stable classification identifier" + }, + "label": { + "type": "string", + "description": "Original label of the classification item, which is useful for search and indexing purposes" + }, + "confidence": { + "type": "number", + "nullable": true, + "description": "Optional confidence score for the classification" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Optional metadata associated with the classification" + }, + "source": { + "$ref": "#/components/schemas/SavedFunctionId" + } + }, + "required": [ + "id" + ] + } + }, + "description": "Classifications for this event (dictionary from classification name to items)" + } + }, + "required": [ + "id", + "_xact_id", + "created", + "project_id", + "dataset_id", + "span_id", + "root_span_id" + ] + }, + "FetchDatasetEventsResponse": { + "type": "object", + "properties": { + "events": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DatasetEvent" + }, + "description": "A list of fetched events" + }, + "cursor": { + "type": "string", + "nullable": true, + "description": "Pagination cursor\n\nPass this string directly as the `cursor` param to your next fetch request to get the next page of results. Not provided if the returned result set is empty." + } + }, + "required": [ + "events" + ] + }, + "FeedbackDatasetItem": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The id of the dataset event to log feedback for. This is the row `id` returned by `POST /v1/dataset/{dataset_id}/insert`" + }, + "comment": { + "type": "string", + "nullable": true, + "description": "An optional comment string to log about the dataset event" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "A dictionary with additional data about the feedback. If you have a `user_id`, you can log it here and access it in the Braintrust UI. Note, this metadata does not correspond to the main event itself, but rather the audit log attached to the event." + }, + "source": { + "type": "string", + "nullable": true, + "enum": [ + "app", + "api", + "external", + null + ], + "description": "The source of the feedback. Must be one of \"external\" (default), \"app\", or \"api\"" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags to log" + } + }, + "required": [ + "id" + ] + }, + "FeedbackDatasetEventRequest": { + "type": "object", + "properties": { + "feedback": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FeedbackDatasetItem" + }, + "description": "A list of dataset feedback items" + } + }, + "required": [ + "feedback" + ] + }, + "DataSummary": { + "type": "object", + "nullable": true, + "properties": { + "total_records": { + "type": "integer", + "minimum": 0, + "description": "Total number of records in the dataset" + } + }, + "required": [ + "total_records" + ], + "description": "Summary of a dataset's data" + }, + "SummarizeDatasetResponse": { + "type": "object", + "properties": { + "project_name": { + "type": "string", + "description": "Name of the project that the dataset belongs to" + }, + "dataset_name": { + "type": "string", + "description": "Name of the dataset" + }, + "project_url": { + "type": "string", + "format": "uri", + "description": "URL to the project's page in the Braintrust app" + }, + "dataset_url": { + "type": "string", + "format": "uri", + "description": "URL to the dataset's page in the Braintrust app" + }, + "data_summary": { + "$ref": "#/components/schemas/DataSummary" + } + }, + "required": [ + "project_name", + "dataset_name", + "project_url", + "dataset_url" + ], + "description": "Summary of a dataset" + }, + "ChatCompletionContentPartText": { + "type": "object", + "properties": { + "text": { + "type": "string", + "default": "" + }, + "type": { + "type": "string", + "enum": [ + "text" + ] + }, + "cache_control": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "ephemeral" + ] + } + }, + "required": [ + "type" + ] + } + }, + "required": [ + "type" + ] + }, + "ChatCompletionContentPartTextWithTitle": { + "type": "object", + "properties": { + "text": { + "type": "string", + "default": "" + }, + "type": { + "type": "string", + "enum": [ + "text" + ] + }, + "cache_control": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "ephemeral" + ] + } + }, + "required": [ + "type" + ] + } + }, + "required": [ + "type" + ], + "title": "text" + }, + "ChatCompletionContentPartImageWithTitle": { + "type": "object", + "properties": { + "image_url": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "detail": { + "anyOf": [ + { + "type": "string", + "enum": [ + "auto" + ], + "title": "auto" + }, + { + "type": "string", + "enum": [ + "low" + ], + "title": "low" + }, + { + "type": "string", + "enum": [ + "high" + ], + "title": "high" + } + ] + } + }, + "required": [ + "url" + ] + }, + "type": { + "type": "string", + "enum": [ + "image_url" + ] + } + }, + "required": [ + "image_url", + "type" + ], + "title": "image_url" + }, + "ChatCompletionContentPartFileFile": { + "type": "object", + "properties": { + "file_data": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "file_id": { + "type": "string", + "title": "The ID of an uploaded file to use as input." + } + } + }, + "ChatCompletionContentPartFileWithTitle": { + "type": "object", + "properties": { + "file": { + "$ref": "#/components/schemas/ChatCompletionContentPartFileFile" + }, + "type": { + "type": "string", + "enum": [ + "file" + ] + } + }, + "required": [ + "file", + "type" + ], + "title": "file" + }, + "ChatCompletionContentPart": { + "anyOf": [ + { + "$ref": "#/components/schemas/ChatCompletionContentPartTextWithTitle" + }, + { + "$ref": "#/components/schemas/ChatCompletionContentPartImageWithTitle" + }, + { + "$ref": "#/components/schemas/ChatCompletionContentPartFileWithTitle" + } + ], + "title": "chat_completion_content_part" + }, + "ChatCompletionMessageToolCall": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "function": { + "type": "object", + "properties": { + "arguments": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "arguments", + "name" + ] + }, + "type": { + "type": "string", + "enum": [ + "function" + ] + } + }, + "required": [ + "id", + "function", + "type" + ] + }, + "ChatCompletionMessageReasoning": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "content": { + "type": "string", + "nullable": true + } + }, + "description": "Note: This is not part of the OpenAI API spec, but we added it for interoperability with multiple reasoning models." + }, + "ChatCompletionMessageParam": { + "anyOf": [ + { + "type": "object", + "properties": { + "content": { + "anyOf": [ + { + "type": "string", + "default": "", + "title": "text" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatCompletionContentPartText" + }, + "title": "array" + } + ] + }, + "role": { + "type": "string", + "enum": [ + "system" + ] + }, + "name": { + "type": "string" + } + }, + "required": [ + "role" + ], + "title": "system" + }, + { + "type": "object", + "properties": { + "content": { + "anyOf": [ + { + "type": "string", + "default": "", + "title": "text" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatCompletionContentPart" + }, + "title": "array" + } + ] + }, + "role": { + "type": "string", + "enum": [ + "user" + ] + }, + "name": { + "type": "string" + } + }, + "required": [ + "role" + ], + "title": "user" + }, + { + "type": "object", + "properties": { + "role": { + "type": "string", + "enum": [ + "assistant" + ] + }, + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatCompletionContentPartText" + } + }, + { + "type": "null" + } + ] + }, + "function_call": { + "type": "object", + "nullable": true, + "properties": { + "arguments": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "arguments", + "name" + ] + }, + "name": { + "type": "string", + "nullable": true + }, + "tool_calls": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/ChatCompletionMessageToolCall" + } + }, + "reasoning": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/ChatCompletionMessageReasoning" + } + }, + "reasoning_signature": { + "type": "string", + "nullable": true + } + }, + "required": [ + "role" + ], + "title": "assistant" + }, + { + "type": "object", + "properties": { + "content": { + "anyOf": [ + { + "type": "string", + "default": "", + "title": "text" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatCompletionContentPartText" + }, + "title": "array" + } + ] + }, + "role": { + "type": "string", + "enum": [ + "tool" + ] + }, + "tool_call_id": { + "type": "string", + "default": "" + } + }, + "required": [ + "role" + ], + "title": "tool" + }, + { + "type": "object", + "properties": { + "content": { + "type": "string", + "nullable": true + }, + "name": { + "type": "string" + }, + "role": { + "type": "string", + "enum": [ + "function" + ] + } + }, + "required": [ + "content", + "name", + "role" + ], + "title": "function" + }, + { + "type": "object", + "properties": { + "content": { + "anyOf": [ + { + "type": "string", + "default": "", + "title": "text" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatCompletionContentPartText" + }, + "title": "array" + } + ] + }, + "role": { + "type": "string", + "enum": [ + "developer" + ] + }, + "name": { + "type": "string" + } + }, + "required": [ + "role" + ], + "title": "developer" + }, + { + "type": "object", + "properties": { + "role": { + "type": "string", + "enum": [ + "model" + ] + }, + "content": { + "type": "string", + "nullable": true + } + }, + "required": [ + "role" + ], + "title": "fallback" + } + ] + }, + "PromptBlockDataNullish": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "chat" + ] + }, + "messages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatCompletionMessageParam" + } + }, + "tools": { + "type": "string" + } + }, + "required": [ + "type", + "messages" + ], + "title": "chat" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "completion" + ] + }, + "content": { + "type": "string" + } + }, + "required": [ + "type", + "content" + ], + "title": "completion" + }, + { + "type": "null" + } + ] + }, + "ResponseFormatJsonSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "schema": { + "anyOf": [ + { + "type": "object", + "additionalProperties": { + "nullable": true + }, + "title": "object", + "x-stainless-skip": [ + "go" + ] + }, + { + "type": "string", + "title": "string" + } + ] + }, + "strict": { + "type": "boolean", + "nullable": true + } + }, + "required": [ + "name" + ] + }, + "ResponseFormatNullish": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "json_object" + ] + } + }, + "required": [ + "type" + ], + "title": "json_object" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "json_schema" + ] + }, + "json_schema": { + "$ref": "#/components/schemas/ResponseFormatJsonSchema" + } + }, + "required": [ + "type", + "json_schema" + ], + "title": "json_schema" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "text" + ] + } + }, + "required": [ + "type" + ], + "title": "text" + }, + { + "type": "null" + } + ] + }, + "ModelParams": { + "anyOf": [ + { + "type": "object", + "properties": { + "use_cache": { + "type": "boolean" + }, + "reasoning_enabled": { + "type": "boolean" + }, + "reasoning_budget": { + "type": "number" + }, + "temperature": { + "type": "number" + }, + "top_p": { + "type": "number" + }, + "max_tokens": { + "type": "number" + }, + "max_completion_tokens": { + "type": "number", + "description": "The successor to max_tokens" + }, + "frequency_penalty": { + "type": "number" + }, + "presence_penalty": { + "type": "number" + }, + "response_format": { + "$ref": "#/components/schemas/ResponseFormatNullish" + }, + "tool_choice": { + "anyOf": [ + { + "type": "string", + "enum": [ + "auto" + ], + "title": "auto" + }, + { + "type": "string", + "enum": [ + "none" + ], + "title": "none" + }, + { + "type": "string", + "enum": [ + "required" + ], + "title": "required" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "function" + ] + }, + "function": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + }, + "required": [ + "type", + "function" + ], + "title": "function" + } + ] + }, + "function_call": { + "anyOf": [ + { + "type": "string", + "enum": [ + "auto" + ], + "title": "auto" + }, + { + "type": "string", + "enum": [ + "none" + ], + "title": "none" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ], + "title": "function" + } + ] + }, + "n": { + "type": "number" + }, + "stop": { + "type": "array", + "items": { + "type": "string" + } + }, + "reasoning_effort": { + "type": "string", + "enum": [ + "none", + "minimal", + "low", + "medium", + "high" + ] + }, + "verbosity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ] + } + }, + "additionalProperties": { + "nullable": true + }, + "title": "OpenAIModelParams", + "x-stainless-skip": [ + "go" + ] + }, + { + "type": "object", + "properties": { + "use_cache": { + "type": "boolean" + }, + "reasoning_enabled": { + "type": "boolean" + }, + "reasoning_budget": { + "type": "number" + }, + "max_tokens": { + "type": "number" + }, + "temperature": { + "type": "number" + }, + "top_p": { + "type": "number" + }, + "top_k": { + "type": "number" + }, + "stop_sequences": { + "type": "array", + "items": { + "type": "string" + } + }, + "max_tokens_to_sample": { + "type": "number", + "description": "This is a legacy parameter that should not be used." + } + }, + "required": [ + "max_tokens", + "temperature" + ], + "additionalProperties": { + "nullable": true + }, + "title": "AnthropicModelParams", + "x-stainless-skip": [ + "go" + ] + }, + { + "type": "object", + "properties": { + "use_cache": { + "type": "boolean" + }, + "reasoning_enabled": { + "type": "boolean" + }, + "reasoning_budget": { + "type": "number" + }, + "temperature": { + "type": "number" + }, + "maxOutputTokens": { + "type": "number" + }, + "topP": { + "type": "number" + }, + "topK": { + "type": "number" + } + }, + "additionalProperties": { + "nullable": true + }, + "title": "GoogleModelParams", + "x-stainless-skip": [ + "go" + ] + }, + { + "type": "object", + "properties": { + "use_cache": { + "type": "boolean" + }, + "reasoning_enabled": { + "type": "boolean" + }, + "reasoning_budget": { + "type": "number" + }, + "temperature": { + "type": "number" + }, + "topK": { + "type": "number" + } + }, + "additionalProperties": { + "nullable": true + }, + "title": "WindowAIModelParams", + "x-stainless-skip": [ + "go" + ] + }, + { + "type": "object", + "properties": { + "use_cache": { + "type": "boolean" + }, + "reasoning_enabled": { + "type": "boolean" + }, + "reasoning_budget": { + "type": "number" + } + }, + "additionalProperties": { + "nullable": true + }, + "title": "JsCompletionParams", + "x-stainless-skip": [ + "go" + ] + } + ] + }, + "PromptOptionsNullish": { + "type": "object", + "nullable": true, + "properties": { + "model": { + "type": "string" + }, + "params": { + "$ref": "#/components/schemas/ModelParams" + }, + "position": { + "type": "string" + } + } + }, + "PromptParserNullish": { + "type": "object", + "nullable": true, + "properties": { + "type": { + "type": "string", + "enum": [ + "llm_classifier" + ] + }, + "use_cot": { + "type": "boolean" + }, + "choice_scores": { + "type": "object", + "additionalProperties": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "description": "Map of choices to scores (0-1). Used by scorers." + }, + "choice": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of valid choices without score mapping. Used by classifiers that deposit output to tags." + }, + "allow_no_match": { + "type": "boolean", + "description": "If true, adds a 'No match' option. When selected, no tag is deposited." + } + }, + "required": [ + "type", + "use_cot" + ] + }, + "PromptDataNullish": { + "type": "object", + "nullable": true, + "properties": { + "prompt": { + "$ref": "#/components/schemas/PromptBlockDataNullish" + }, + "options": { + "$ref": "#/components/schemas/PromptOptionsNullish" + }, + "parser": { + "$ref": "#/components/schemas/PromptParserNullish" + }, + "tool_functions": { + "type": "array", + "nullable": true, + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/SavedFunctionId" + }, + { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "function" + ] + }, + "id": { + "type": "string" + }, + "version": { + "type": "string", + "description": "The version of the function" + } + }, + "required": [ + "type", + "id" + ], + "title": "function" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "global" + ] + }, + "name": { + "type": "string" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + } + }, + "required": [ + "type", + "name" + ], + "title": "global" + } + ] + } + ] + } + }, + "template_format": { + "type": "string", + "nullable": true, + "enum": [ + "mustache", + "nunjucks", + "none", + null + ] + }, + "mcp": { + "type": "object", + "nullable": true, + "additionalProperties": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "id" + ] + }, + "id": { + "type": "string", + "format": "uuid" + }, + "is_disabled": { + "type": "boolean" + }, + "enabled_tools": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "If omitted, all tools are enabled" + } + }, + "required": [ + "type", + "id" + ], + "title": "MCP server id. This is used for project-level MCP server definitions." + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "url" + ] + }, + "url": { + "type": "string" + }, + "is_disabled": { + "type": "boolean" + }, + "enabled_tools": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "If omitted, all tools are enabled" + } + }, + "required": [ + "type", + "url" + ], + "title": "MCP server url. This is used for inline definitions of MCP servers." + } + ] + } + }, + "origin": { + "type": "object", + "nullable": true, + "properties": { + "prompt_id": { + "type": "string" + }, + "project_id": { + "type": "string" + }, + "prompt_version": { + "type": "string" + } + } + } + }, + "description": "The prompt, model, and its parameters" + }, + "FunctionTypeEnumNullish": { + "type": "string", + "nullable": true, + "enum": [ + "llm", + "scorer", + "task", + "tool", + "custom_view", + "preprocessor", + "facet", + "classifier", + "tag", + "parameters", + "sandbox", + null + ] + }, + "Prompt": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the prompt" + }, + "_xact_id": { + "type": "string", + "description": "The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the prompt (see the `version` parameter)" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the prompt belongs under" + }, + "log_id": { + "type": "string", + "enum": [ + "p" + ], + "description": "A literal 'p' which identifies the object as a project prompt" + }, + "org_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the organization" + }, + "name": { + "type": "string", + "description": "Name of the prompt" + }, + "slug": { + "type": "string", + "description": "Unique identifier for the prompt" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the prompt" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of prompt creation" + }, + "prompt_data": { + "$ref": "#/components/schemas/PromptDataNullish" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the prompt" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "User-controlled metadata about the prompt" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnumNullish" + } + }, + "required": [ + "id", + "_xact_id", + "project_id", + "log_id", + "org_id", + "name", + "slug" + ] + }, + "CreatePrompt": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the prompt belongs under" + }, + "name": { + "type": "string", + "minLength": 1, + "description": "Name of the prompt" + }, + "slug": { + "type": "string", + "minLength": 1, + "description": "Unique identifier for the prompt" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the prompt" + }, + "prompt_data": { + "$ref": "#/components/schemas/PromptDataNullish" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the prompt" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnumNullish" + } + }, + "required": [ + "project_id", + "name", + "slug" + ] + }, + "PatchPrompt": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the prompt" + }, + "slug": { + "type": "string", + "nullable": true, + "description": "Unique identifier for the prompt" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the prompt" + }, + "prompt_data": { + "$ref": "#/components/schemas/PromptDataNullish" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the prompt" + } + } + }, + "Permission": { + "type": "string", + "enum": [ + "create", + "read", + "update", + "delete", + "create_acls", + "read_acls", + "update_acls", + "delete_acls" + ], + "description": "Each permission permits a certain type of operation on an object in the system\n\nPermissions can be assigned to to objects on an individual basis, or grouped into roles" + }, + "Role": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the role" + }, + "org_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Unique id for the organization that the role belongs under\n\nA null org_id indicates a system role, which may be assigned to anybody and inherited by any other role, but cannot be edited.\n\nIt is forbidden to change the org after creating a role" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifies the user who created the role" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of role creation" + }, + "name": { + "type": "string", + "description": "Name of the role" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the role" + }, + "deleted_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of role deletion, or null if the role is still active" + }, + "member_permissions": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "permission": { + "$ref": "#/components/schemas/Permission" + }, + "restrict_object_type": { + "$ref": "#/components/schemas/AclObjectType", + "nullable": true + } + }, + "required": [ + "permission" + ] + }, + "description": "(permission, restrict_object_type) tuples which belong to this role" + }, + "member_roles": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "Ids of the roles this role inherits from\n\nAn inheriting role has all the permissions contained in its member roles, as well as all of their inherited permissions" + } + }, + "required": [ + "id", + "name" + ], + "description": "A role is a collection of permissions which can be granted as part of an ACL\n\nRoles can consist of individual permissions, as well as a set of roles they inherit from" + }, + "CreateRole": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "Name of the role" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the role" + }, + "member_permissions": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "permission": { + "$ref": "#/components/schemas/Permission" + }, + "restrict_object_type": { + "$ref": "#/components/schemas/AclObjectType", + "nullable": true + } + }, + "required": [ + "permission" + ] + }, + "description": "(permission, restrict_object_type) tuples which belong to this role" + }, + "member_roles": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "Ids of the roles this role inherits from\n\nAn inheriting role has all the permissions contained in its member roles, as well as all of their inherited permissions" + }, + "org_name": { + "type": "string", + "nullable": true, + "description": "For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the role belongs in." + } + }, + "required": [ + "name" + ] + }, + "PatchRole": { + "type": "object", + "properties": { + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the role" + }, + "name": { + "type": "string", + "nullable": true, + "minLength": 1, + "description": "Name of the role" + }, + "add_member_permissions": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "permission": { + "$ref": "#/components/schemas/Permission" + }, + "restrict_object_type": { + "$ref": "#/components/schemas/AclObjectType", + "nullable": true + } + }, + "required": [ + "permission" + ] + }, + "description": "A list of permissions to add to the role" + }, + "remove_member_permissions": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "permission": { + "$ref": "#/components/schemas/Permission" + }, + "restrict_object_type": { + "$ref": "#/components/schemas/AclObjectType", + "nullable": true + } + }, + "required": [ + "permission" + ] + }, + "description": "A list of permissions to remove from the role" + }, + "add_member_roles": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "A list of role IDs to add to the role's inheriting-from set" + }, + "remove_member_roles": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "A list of role IDs to remove from the role's inheriting-from set" + } + } + }, + "Group": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the group" + }, + "org_id": { + "type": "string", + "format": "uuid", + "description": "Unique id for the organization that the group belongs under\n\nIt is forbidden to change the org after creating a group" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifies the user who created the group" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of group creation" + }, + "name": { + "type": "string", + "description": "Name of the group" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the group" + }, + "deleted_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of group deletion, or null if the group is still active" + }, + "member_users": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "Ids of users which belong to this group" + }, + "member_groups": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "Ids of the groups this group inherits from\n\nAn inheriting group has all the users contained in its member groups, as well as all of their inherited users" + } + }, + "required": [ + "id", + "org_id", + "name" + ], + "description": "A group is a collection of users which can be assigned an ACL\n\nGroups can consist of individual users, as well as a set of groups they inherit from" + }, + "CreateGroup": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "Name of the group" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the group" + }, + "member_users": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "Ids of users which belong to this group" + }, + "member_groups": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "Ids of the groups this group inherits from\n\nAn inheriting group has all the users contained in its member groups, as well as all of their inherited users" + }, + "org_name": { + "type": "string", + "nullable": true, + "description": "For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the group belongs in." + } + }, + "required": [ + "name" + ] + }, + "PatchGroup": { + "type": "object", + "properties": { + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the group" + }, + "name": { + "type": "string", + "nullable": true, + "minLength": 1, + "description": "Name of the group" + }, + "add_member_users": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "A list of user IDs to add to the group" + }, + "remove_member_users": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "A list of user IDs to remove from the group" + }, + "add_member_groups": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "A list of group IDs to add to the group's inheriting-from set" + }, + "remove_member_groups": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "A list of group IDs to remove from the group's inheriting-from set" + } + } + }, + "Acl": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the acl" + }, + "object_type": { + "$ref": "#/components/schemas/AclObjectType" + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "The id of the object the ACL applies to" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Id of the user the ACL applies to. Exactly one of `user_id` and `group_id` will be provided" + }, + "group_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Id of the group the ACL applies to. Exactly one of `user_id` and `group_id` will be provided" + }, + "permission": { + "$ref": "#/components/schemas/Permission", + "nullable": true, + "description": "Permission the ACL grants. Exactly one of `permission` and `role_id` will be provided" + }, + "restrict_object_type": { + "$ref": "#/components/schemas/AclObjectType", + "nullable": true, + "description": "When setting a permission directly, optionally restricts the permission grant to just the specified object type. Cannot be set alongside a `role_id`." + }, + "role_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Id of the role the ACL grants. Exactly one of `permission` and `role_id` will be provided" + }, + "_object_org_id": { + "type": "string", + "format": "uuid", + "description": "The organization the ACL's referred object belongs to" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of acl creation" + } + }, + "required": [ + "id", + "object_type", + "object_id", + "_object_org_id" + ], + "description": "An ACL grants a certain permission or role to a certain user or group on an object.\n\nACLs are inherited across the object hierarchy. So for example, if a user has read permissions on a project, they will also have read permissions on any experiment, dataset, etc. created within that project.\n\nTo restrict a grant to a particular sub-object, you may specify `restrict_object_type` in the ACL, as part of a direct permission grant or as part of a role." + }, + "AclItem": { + "type": "object", + "properties": { + "object_type": { + "$ref": "#/components/schemas/AclObjectType" + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "The id of the object the ACL applies to" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Id of the user the ACL applies to. Exactly one of `user_id` and `group_id` will be provided" + }, + "group_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Id of the group the ACL applies to. Exactly one of `user_id` and `group_id` will be provided" + }, + "permission": { + "$ref": "#/components/schemas/Permission", + "nullable": true, + "description": "Permission the ACL grants. Exactly one of `permission` and `role_id` will be provided" + }, + "restrict_object_type": { + "$ref": "#/components/schemas/AclObjectType", + "nullable": true, + "description": "When setting a permission directly, optionally restricts the permission grant to just the specified object type. Cannot be set alongside a `role_id`." + }, + "role_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Id of the role the ACL grants. Exactly one of `permission` and `role_id` will be provided" + } + }, + "required": [ + "object_type", + "object_id" + ], + "description": "An ACL grants a certain permission or role to a certain user or group on an object.\n\nACLs are inherited across the object hierarchy. So for example, if a user has read permissions on a project, they will also have read permissions on any experiment, dataset, etc. created within that project.\n\nTo restrict a grant to a particular sub-object, you may specify `restrict_object_type` in the ACL, as part of a direct permission grant or as part of a role." + }, + "AclBatchUpdateResponse": { + "type": "object", + "properties": { + "added_acls": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Acl" + } + }, + "removed_acls": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Acl" + } + } + }, + "required": [ + "added_acls", + "removed_acls" + ] + }, + "AclBatchUpdateRequest": { + "type": "object", + "properties": { + "add_acls": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/AclItem" + } + }, + "remove_acls": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/AclItem" + } + } + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the user" + }, + "given_name": { + "type": "string", + "nullable": true, + "description": "Given name of the user" + }, + "family_name": { + "type": "string", + "nullable": true, + "description": "Family name of the user" + }, + "email": { + "type": "string", + "nullable": true, + "description": "The user's email" + }, + "avatar_url": { + "type": "string", + "nullable": true, + "description": "URL of the user's Avatar image" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of user creation" + } + }, + "required": [ + "id" + ] + }, + "Agent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the agent" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the agent belongs under" + }, + "user_id": { + "type": "string", + "format": "uuid" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of agent creation" + }, + "name": { + "type": "string", + "description": "Name of the agent. Within a project, agent names are unique" + }, + "slug": { + "type": "string", + "description": "Stable, URL-safe identifier for the agent, unique within its project." + }, + "kind": { + "type": "string", + "description": "Agent classification: 'custom' for customer-defined agents, 'loop' for built-in Loop agents." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the agent" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "User-controlled metadata about the agent" + } + }, + "required": [ + "id", + "project_id", + "user_id", + "name", + "slug", + "kind" + ], + "description": "An agent is a project-scoped durable object that identifies an AI agent or service emitting spans" + }, + "CreateAgent": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the agent belongs under" + }, + "name": { + "type": "string", + "description": "Name of the agent. Within a project, agent names are unique" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the agent" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "User-controlled metadata about the agent" + } + }, + "required": [ + "project_id", + "name" + ], + "description": "An agent is a project-scoped durable object that identifies an AI agent or service emitting spans" + }, + "PatchAgent": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the agent. Within a project, agent names are unique" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the agent" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "User-controlled metadata about the agent" + } + }, + "description": "An agent is a project-scoped durable object that identifies an AI agent or service emitting spans" + }, + "AutomationStatus": { + "type": "string", + "enum": [ + "active", + "paused" + ], + "description": "Whether the automation is active or paused." + }, + "SpanScope": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "span" + ] + } + }, + "required": [ + "type" + ], + "description": "Process individual spans" + }, + "TraceScope": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "trace" + ] + }, + "idle_seconds": { + "type": "number", + "description": "Consider trace complete after this many seconds of inactivity (default: 30)" + } + }, + "required": [ + "type" + ], + "description": "Process entire traces (all spans sharing the same root_span_id)" + }, + "GroupScope": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "group" + ] + }, + "group_by": { + "type": "string", + "description": "Field path to group by, e.g. metadata.session_id" + }, + "interval_seconds": { + "type": "number", + "minimum": 1, + "description": "Maximum time range to include when constructing a group" + }, + "max_traces": { + "type": "integer", + "minimum": 1, + "maximum": 64, + "description": "Maximum number of traces to include when constructing a group (default/max: 64)" + }, + "placement": { + "type": "string", + "enum": [ + "first", + "each" + ], + "description": "Which trace or traces to write grouped scorer results to" + }, + "idle_seconds": { + "type": "number", + "description": "Optional: trigger after this many seconds of inactivity" + } + }, + "required": [ + "type", + "group_by", + "placement" + ], + "description": "Process spans/traces grouped by a field (e.g., session_id)" + }, + "RetentionObjectType": { + "type": "string", + "enum": [ + "project_logs", + "experiment", + "dataset" + ], + "description": "The object type that the retention policy applies to" + }, + "TopicAutomationFacetModel": { + "type": "string", + "nullable": true, + "enum": [ + "brain-facet-latest", + "brain-facet-1", + "brain-facet-2", + null + ], + "description": "Optional facet model override for topic automation" + }, + "TopicMapFunctionAutomation": { + "type": "object", + "properties": { + "function": { + "allOf": [ + { + "$ref": "#/components/schemas/SavedFunctionId" + }, + { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "function" + ] + }, + "id": { + "type": "string" + }, + "version": { + "type": "string", + "description": "The version of the function" + } + }, + "required": [ + "type", + "id" + ], + "title": "function" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "global" + ] + }, + "name": { + "type": "string" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + } + }, + "required": [ + "type", + "name" + ], + "title": "global" + } + ], + "description": "Topic map function" + } + ] + }, + "btql_filter": { + "type": "string", + "nullable": true, + "description": "Per-topic-map BTQL filter. For trace scope, a topic map runs when max(filter) over the trace is truthy. For span scope, it runs when the current span matches." + } + }, + "required": [ + "function" + ] + }, + "TopicAutomationDataScope": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "project_logs" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "project_experiments" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "experiment" + ] + }, + "experiment_id": { + "type": "string" + } + }, + "required": [ + "type", + "experiment_id" + ] + }, + { + "type": "null" + } + ], + "description": "Optional data scope for topic automation." + }, + "TopicAutomationConfig": { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "topic" + ], + "description": "The type of automation." + }, + "status": { + "$ref": "#/components/schemas/AutomationStatus" + }, + "sampling_rate": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "The sampling rate for topic automation" + }, + "facet_model": { + "$ref": "#/components/schemas/TopicAutomationFacetModel" + }, + "facet_functions": { + "type": "array", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/SavedFunctionId" + }, + { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "function" + ] + }, + "id": { + "type": "string" + }, + "version": { + "type": "string", + "description": "The version of the function" + } + }, + "required": [ + "type", + "id" + ], + "title": "function" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "global" + ] + }, + "name": { + "type": "string" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + } + }, + "required": [ + "type", + "name" + ], + "title": "global" + } + ] + } + ] + }, + "description": "Facet functions used by the topic automation" + }, + "topic_map_functions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TopicMapFunctionAutomation" + }, + "description": "Topic map functions with optional per-topic-map filters" + }, + "scope": { + "anyOf": [ + { + "$ref": "#/components/schemas/SpanScope" + }, + { + "$ref": "#/components/schemas/TraceScope" + }, + { + "$ref": "#/components/schemas/GroupScope" + }, + { + "type": "null" + } + ], + "description": "Execution scope for topic automation. Defaults to span-level execution." + }, + "data_scope": { + "$ref": "#/components/schemas/TopicAutomationDataScope" + }, + "btql_filter": { + "type": "string", + "nullable": true, + "description": "Optional BTQL filter applied before topic automation." + }, + "rerun_seconds": { + "type": "number", + "nullable": true, + "minimum": 600, + "description": "How often to recompute topic maps" + }, + "relabel_overlap_seconds": { + "type": "number", + "nullable": true, + "minimum": 60, + "description": "How much recent history to relabel after a new topic map version becomes active" + }, + "backfill_time_range": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "from": { + "type": "string" + }, + "to": { + "type": "string" + } + }, + "required": [ + "from", + "to" + ] + }, + { + "type": "null" + } + ], + "description": "Topic window used for classification coverage and initial backfill." + } + }, + "required": [ + "event_type", + "sampling_rate", + "facet_functions", + "topic_map_functions" + ] + }, + "TopicDigestAutomationConfig": { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "topic_digest" + ], + "description": "The type of automation." + }, + "status": { + "$ref": "#/components/schemas/AutomationStatus" + }, + "window_seconds": { + "type": "integer", + "minimum": 3600, + "maximum": 2592000, + "default": 86400, + "description": "How much recent history to include in each digest" + }, + "scheduled_time_minutes_utc": { + "type": "integer", + "minimum": 0, + "maximum": 1439, + "description": "Minutes after midnight UTC when the digest should be sent" + }, + "action": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "slack" + ], + "description": "The type of action to take" + }, + "workspace_id": { + "type": "string", + "description": "The Slack workspace ID to post to" + }, + "channel": { + "type": "string", + "description": "The Slack channel ID to post to" + }, + "message_template": { + "type": "string", + "description": "Custom message template for the alert" + } + }, + "required": [ + "type", + "workspace_id", + "channel" + ], + "description": "The Slack action to take when the digest is sent" + }, + "topic_map_function_ids": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 10, + "description": "Optional topic map function IDs to include in the digest" + } + }, + "required": [ + "event_type", + "scheduled_time_minutes_utc", + "action" + ] + }, + "ProjectAutomation": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project automation" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the project automation belongs under" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifies the user who created the project automation" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of project automation creation" + }, + "name": { + "type": "string", + "description": "Name of the project automation" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the project automation" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "logs" + ], + "description": "The type of automation." + }, + "btql_filter": { + "type": "string", + "description": "BTQL filter to identify rows for the automation rule" + }, + "interval_seconds": { + "type": "number", + "minimum": 1, + "maximum": 2592000, + "description": "Perform the triggered action at most once in this interval of seconds" + }, + "action": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "webhook" + ], + "description": "The type of action to take" + }, + "url": { + "type": "string", + "description": "The webhook URL to send the request to" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "slack" + ], + "description": "The type of action to take" + }, + "workspace_id": { + "type": "string", + "description": "The Slack workspace ID to post to" + }, + "channel": { + "type": "string", + "description": "The Slack channel ID to post to" + }, + "message_template": { + "type": "string", + "description": "Custom message template for the alert" + } + }, + "required": [ + "type", + "workspace_id", + "channel" + ] + } + ], + "description": "The action to take when the automation rule is triggered" + } + }, + "required": [ + "event_type", + "btql_filter", + "interval_seconds", + "action" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "btql_export" + ], + "description": "The type of automation." + }, + "status": { + "$ref": "#/components/schemas/AutomationStatus" + }, + "export_definition": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "log_traces" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "log_spans" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "btql_query" + ] + }, + "btql_query": { + "type": "string", + "description": "The BTQL query to export" + } + }, + "required": [ + "type", + "btql_query" + ] + } + ], + "description": "The definition of what to export" + }, + "scope": { + "anyOf": [ + { + "$ref": "#/components/schemas/SpanScope" + }, + { + "$ref": "#/components/schemas/TraceScope" + }, + { + "$ref": "#/components/schemas/GroupScope" + }, + { + "type": "null" + } + ], + "description": "Execution scope for export automation. Defaults to span-level execution." + }, + "export_path": { + "type": "string", + "description": "The path to export the results to. It should include the storage protocol and prefix, e.g. s3://bucket-name/path/to/export" + }, + "format": { + "type": "string", + "enum": [ + "jsonl", + "parquet" + ], + "description": "The format to export the results in" + }, + "interval_seconds": { + "type": "number", + "minimum": 1, + "maximum": 2592000, + "description": "Perform the triggered action at most once in this interval of seconds" + }, + "credentials": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "aws_iam" + ] + }, + "role_arn": { + "type": "string", + "description": "The ARN of the IAM role to use" + }, + "external_id": { + "type": "string", + "description": "The automation-specific external id component (auto-generated by default)" + } + }, + "required": [ + "type", + "role_arn", + "external_id" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "gcp_service_account" + ] + }, + "service_account_email": { + "type": "string", + "description": "The GCP service account email to impersonate" + } + }, + "required": [ + "type", + "service_account_email" + ] + } + ] + }, + "batch_size": { + "type": "number", + "nullable": true, + "description": "The number of rows to export in each batch" + } + }, + "required": [ + "event_type", + "export_definition", + "export_path", + "format", + "interval_seconds", + "credentials" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "async_query" + ], + "description": "The type of automation." + }, + "status": { + "$ref": "#/components/schemas/AutomationStatus" + }, + "created_by_user_id": { + "type": "string", + "format": "uuid", + "description": "The user who submitted the async query" + }, + "object_type": { + "type": "string", + "enum": [ + "project_logs", + "experiment", + "dataset", + "playground_logs" + ], + "description": "The source object type for the async query" + }, + "object_id": { + "type": "string", + "description": "The source object ID for the async query" + }, + "query": { + "type": "string", + "description": "The SQL query to execute asynchronously" + }, + "format": { + "type": "string", + "enum": [ + "jsonl" + ], + "description": "The materialized result format" + }, + "batch_size": { + "type": "integer", + "nullable": true, + "minimum": 0, + "exclusiveMinimum": true, + "maximum": 100000, + "description": "The maximum number of result rows to write per async query batch" + } + }, + "required": [ + "event_type", + "created_by_user_id", + "object_type", + "object_id", + "query", + "format" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "retention" + ], + "description": "The type of automation." + }, + "object_type": { + "$ref": "#/components/schemas/RetentionObjectType" + }, + "retention_days": { + "type": "number", + "minimum": 0, + "description": "The number of days to retain the object" + } + }, + "required": [ + "event_type", + "object_type", + "retention_days" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "environment_update" + ], + "description": "The type of automation." + }, + "environment_filter": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional list of environment slugs to filter by" + }, + "action": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "webhook" + ], + "description": "The type of action to take" + }, + "url": { + "type": "string", + "description": "The webhook URL to send the request to" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "slack" + ], + "description": "The type of action to take" + }, + "workspace_id": { + "type": "string", + "description": "The Slack workspace ID to post to" + }, + "channel": { + "type": "string", + "description": "The Slack channel ID to post to" + }, + "message_template": { + "type": "string", + "description": "Custom message template for the alert" + } + }, + "required": [ + "type", + "workspace_id", + "channel" + ] + } + ], + "description": "The action to take when the automation rule is triggered" + } + }, + "required": [ + "event_type", + "action" + ] + }, + { + "$ref": "#/components/schemas/TopicAutomationConfig" + }, + { + "$ref": "#/components/schemas/TopicDigestAutomationConfig" + } + ], + "description": "The configuration for the automation rule" + } + }, + "required": [ + "id", + "project_id", + "name", + "config" + ] + }, + "CreateProjectAutomation": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the project automation belongs under" + }, + "name": { + "type": "string", + "description": "Name of the project automation" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the project automation" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "logs" + ], + "description": "The type of automation." + }, + "btql_filter": { + "type": "string", + "description": "BTQL filter to identify rows for the automation rule" + }, + "interval_seconds": { + "type": "number", + "minimum": 1, + "maximum": 2592000, + "description": "Perform the triggered action at most once in this interval of seconds" + }, + "action": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "webhook" + ], + "description": "The type of action to take" + }, + "url": { + "type": "string", + "description": "The webhook URL to send the request to" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "slack" + ], + "description": "The type of action to take" + }, + "workspace_id": { + "type": "string", + "description": "The Slack workspace ID to post to" + }, + "channel": { + "type": "string", + "description": "The Slack channel ID to post to" + }, + "message_template": { + "type": "string", + "description": "Custom message template for the alert" + } + }, + "required": [ + "type", + "workspace_id", + "channel" + ] + } + ], + "description": "The action to take when the automation rule is triggered" + } + }, + "required": [ + "event_type", + "btql_filter", + "interval_seconds", + "action" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "btql_export" + ], + "description": "The type of automation." + }, + "status": { + "$ref": "#/components/schemas/AutomationStatus" + }, + "export_definition": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "log_traces" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "log_spans" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "btql_query" + ] + }, + "btql_query": { + "type": "string", + "description": "The BTQL query to export" + } + }, + "required": [ + "type", + "btql_query" + ] + } + ], + "description": "The definition of what to export" + }, + "scope": { + "anyOf": [ + { + "$ref": "#/components/schemas/SpanScope" + }, + { + "$ref": "#/components/schemas/TraceScope" + }, + { + "$ref": "#/components/schemas/GroupScope" + }, + { + "type": "null" + } + ], + "description": "Execution scope for export automation. Defaults to span-level execution." + }, + "export_path": { + "type": "string", + "description": "The path to export the results to. It should include the storage protocol and prefix, e.g. s3://bucket-name/path/to/export" + }, + "format": { + "type": "string", + "enum": [ + "jsonl", + "parquet" + ], + "description": "The format to export the results in" + }, + "interval_seconds": { + "type": "number", + "minimum": 1, + "maximum": 2592000, + "description": "Perform the triggered action at most once in this interval of seconds" + }, + "credentials": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "aws_iam" + ] + }, + "role_arn": { + "type": "string", + "description": "The ARN of the IAM role to use" + }, + "external_id": { + "type": "string", + "description": "The automation-specific external id component (auto-generated by default)" + } + }, + "required": [ + "type", + "role_arn", + "external_id" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "gcp_service_account" + ] + }, + "service_account_email": { + "type": "string", + "description": "The GCP service account email to impersonate" + } + }, + "required": [ + "type", + "service_account_email" + ] + } + ] + }, + "batch_size": { + "type": "number", + "nullable": true, + "description": "The number of rows to export in each batch" + } + }, + "required": [ + "event_type", + "export_definition", + "export_path", + "format", + "interval_seconds", + "credentials" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "async_query" + ], + "description": "The type of automation." + }, + "status": { + "$ref": "#/components/schemas/AutomationStatus" + }, + "created_by_user_id": { + "type": "string", + "format": "uuid", + "description": "The user who submitted the async query" + }, + "object_type": { + "type": "string", + "enum": [ + "project_logs", + "experiment", + "dataset", + "playground_logs" + ], + "description": "The source object type for the async query" + }, + "object_id": { + "type": "string", + "description": "The source object ID for the async query" + }, + "query": { + "type": "string", + "description": "The SQL query to execute asynchronously" + }, + "format": { + "type": "string", + "enum": [ + "jsonl" + ], + "description": "The materialized result format" + }, + "batch_size": { + "type": "integer", + "nullable": true, + "minimum": 0, + "exclusiveMinimum": true, + "maximum": 100000, + "description": "The maximum number of result rows to write per async query batch" + } + }, + "required": [ + "event_type", + "created_by_user_id", + "object_type", + "object_id", + "query", + "format" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "retention" + ], + "description": "The type of automation." + }, + "object_type": { + "$ref": "#/components/schemas/RetentionObjectType" + }, + "retention_days": { + "type": "number", + "minimum": 0, + "description": "The number of days to retain the object" + } + }, + "required": [ + "event_type", + "object_type", + "retention_days" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "environment_update" + ], + "description": "The type of automation." + }, + "environment_filter": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional list of environment slugs to filter by" + }, + "action": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "webhook" + ], + "description": "The type of action to take" + }, + "url": { + "type": "string", + "description": "The webhook URL to send the request to" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "slack" + ], + "description": "The type of action to take" + }, + "workspace_id": { + "type": "string", + "description": "The Slack workspace ID to post to" + }, + "channel": { + "type": "string", + "description": "The Slack channel ID to post to" + }, + "message_template": { + "type": "string", + "description": "Custom message template for the alert" + } + }, + "required": [ + "type", + "workspace_id", + "channel" + ] + } + ], + "description": "The action to take when the automation rule is triggered" + } + }, + "required": [ + "event_type", + "action" + ] + }, + { + "$ref": "#/components/schemas/TopicAutomationConfig" + }, + { + "$ref": "#/components/schemas/TopicDigestAutomationConfig" + } + ], + "description": "The configuration for the automation rule" + } + }, + "required": [ + "project_id", + "name", + "config" + ] + }, + "PatchProjectAutomation": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the project automation" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the project automation" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "logs" + ], + "description": "The type of automation." + }, + "btql_filter": { + "type": "string", + "description": "BTQL filter to identify rows for the automation rule" + }, + "interval_seconds": { + "type": "number", + "minimum": 1, + "maximum": 2592000, + "description": "Perform the triggered action at most once in this interval of seconds" + }, + "action": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "webhook" + ], + "description": "The type of action to take" + }, + "url": { + "type": "string", + "description": "The webhook URL to send the request to" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "slack" + ], + "description": "The type of action to take" + }, + "workspace_id": { + "type": "string", + "description": "The Slack workspace ID to post to" + }, + "channel": { + "type": "string", + "description": "The Slack channel ID to post to" + }, + "message_template": { + "type": "string", + "description": "Custom message template for the alert" + } + }, + "required": [ + "type", + "workspace_id", + "channel" + ] + } + ], + "description": "The action to take when the automation rule is triggered" + } + }, + "required": [ + "event_type", + "btql_filter", + "interval_seconds", + "action" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "btql_export" + ], + "description": "The type of automation." + }, + "status": { + "$ref": "#/components/schemas/AutomationStatus" + }, + "export_definition": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "log_traces" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "log_spans" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "btql_query" + ] + }, + "btql_query": { + "type": "string", + "description": "The BTQL query to export" + } + }, + "required": [ + "type", + "btql_query" + ] + } + ], + "description": "The definition of what to export" + }, + "scope": { + "anyOf": [ + { + "$ref": "#/components/schemas/SpanScope" + }, + { + "$ref": "#/components/schemas/TraceScope" + }, + { + "$ref": "#/components/schemas/GroupScope" + }, + { + "type": "null" + } + ], + "description": "Execution scope for export automation. Defaults to span-level execution." + }, + "export_path": { + "type": "string", + "description": "The path to export the results to. It should include the storage protocol and prefix, e.g. s3://bucket-name/path/to/export" + }, + "format": { + "type": "string", + "enum": [ + "jsonl", + "parquet" + ], + "description": "The format to export the results in" + }, + "interval_seconds": { + "type": "number", + "minimum": 1, + "maximum": 2592000, + "description": "Perform the triggered action at most once in this interval of seconds" + }, + "credentials": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "aws_iam" + ] + }, + "role_arn": { + "type": "string", + "description": "The ARN of the IAM role to use" + }, + "external_id": { + "type": "string", + "description": "The automation-specific external id component (auto-generated by default)" + } + }, + "required": [ + "type", + "role_arn", + "external_id" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "gcp_service_account" + ] + }, + "service_account_email": { + "type": "string", + "description": "The GCP service account email to impersonate" + } + }, + "required": [ + "type", + "service_account_email" + ] + } + ] + }, + "batch_size": { + "type": "number", + "nullable": true, + "description": "The number of rows to export in each batch" + } + }, + "required": [ + "event_type", + "export_definition", + "export_path", + "format", + "interval_seconds", + "credentials" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "async_query" + ], + "description": "The type of automation." + }, + "status": { + "$ref": "#/components/schemas/AutomationStatus" + }, + "created_by_user_id": { + "type": "string", + "format": "uuid", + "description": "The user who submitted the async query" + }, + "object_type": { + "type": "string", + "enum": [ + "project_logs", + "experiment", + "dataset", + "playground_logs" + ], + "description": "The source object type for the async query" + }, + "object_id": { + "type": "string", + "description": "The source object ID for the async query" + }, + "query": { + "type": "string", + "description": "The SQL query to execute asynchronously" + }, + "format": { + "type": "string", + "enum": [ + "jsonl" + ], + "description": "The materialized result format" + }, + "batch_size": { + "type": "integer", + "nullable": true, + "minimum": 0, + "exclusiveMinimum": true, + "maximum": 100000, + "description": "The maximum number of result rows to write per async query batch" + } + }, + "required": [ + "event_type", + "created_by_user_id", + "object_type", + "object_id", + "query", + "format" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "retention" + ], + "description": "The type of automation." + }, + "object_type": { + "$ref": "#/components/schemas/RetentionObjectType" + }, + "retention_days": { + "type": "number", + "minimum": 0, + "description": "The number of days to retain the object" + } + }, + "required": [ + "event_type", + "object_type", + "retention_days" + ] + }, + { + "type": "object", + "properties": { + "event_type": { + "type": "string", + "enum": [ + "environment_update" + ], + "description": "The type of automation." + }, + "environment_filter": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional list of environment slugs to filter by" + }, + "action": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "webhook" + ], + "description": "The type of action to take" + }, + "url": { + "type": "string", + "description": "The webhook URL to send the request to" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "slack" + ], + "description": "The type of action to take" + }, + "workspace_id": { + "type": "string", + "description": "The Slack workspace ID to post to" + }, + "channel": { + "type": "string", + "description": "The Slack channel ID to post to" + }, + "message_template": { + "type": "string", + "description": "Custom message template for the alert" + } + }, + "required": [ + "type", + "workspace_id", + "channel" + ] + } + ], + "description": "The action to take when the automation rule is triggered" + } + }, + "required": [ + "event_type", + "action" + ] + }, + { + "$ref": "#/components/schemas/TopicAutomationConfig" + }, + { + "$ref": "#/components/schemas/TopicDigestAutomationConfig" + }, + { + "nullable": true + } + ], + "description": "The configuration for the automation rule" + } + } + }, + "ProjectScoreCategory": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the category" + }, + "value": { + "type": "number", + "description": "Numerical value of the category. Must be between 0 and 1, inclusive" + } + }, + "required": [ + "name", + "value" + ], + "description": "For categorical-type project scores, defines a single category" + }, + "ProjectScoreCategories": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectScoreCategory" + }, + "description": "For categorical-type project scores, the list of all categories", + "title": "categorical" + }, + { + "type": "object", + "additionalProperties": { + "type": "number" + }, + "description": "For weighted-type project scores, the weights of each score", + "title": "weighted", + "x-stainless-skip": [ + "go" + ] + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "For minimum-type project scores, the list of included scores", + "title": "minimum" + }, + { + "type": "null" + } + ] + }, + "OnlineScoreConfig": { + "type": "object", + "nullable": true, + "properties": { + "sampling_rate": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "The sampling rate for online scoring" + }, + "scorers": { + "type": "array", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/SavedFunctionId" + }, + { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "function" + ] + }, + "id": { + "type": "string" + }, + "version": { + "type": "string", + "description": "The version of the function" + } + }, + "required": [ + "type", + "id" + ], + "title": "function" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "global" + ] + }, + "name": { + "type": "string" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + } + }, + "required": [ + "type", + "name" + ], + "title": "global" + } + ] + } + ] + }, + "description": "The list of functions to run for online scoring. Can include scorers, facets, or other function types." + }, + "btql_filter": { + "type": "string", + "nullable": true, + "description": "Filter logs using BTQL" + }, + "apply_to_root_span": { + "type": "boolean", + "nullable": true, + "description": "Whether to trigger online scoring on the root span of each trace. Only applies when scope is 'span' or unset." + }, + "apply_to_span_names": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "Trigger online scoring on any spans with a name in this list. Only applies when scope is 'span' or unset." + }, + "skip_logging": { + "type": "boolean", + "nullable": true, + "description": "Whether to skip adding scorer spans when computing scores" + }, + "scope": { + "anyOf": [ + { + "$ref": "#/components/schemas/SpanScope" + }, + { + "$ref": "#/components/schemas/TraceScope" + }, + { + "$ref": "#/components/schemas/GroupScope" + }, + { + "type": "null" + } + ], + "description": "The scope at which to run the functions. Defaults to span-level execution." + } + }, + "required": [ + "sampling_rate", + "scorers" + ] + }, + "ProjectScoreCondition": { + "type": "object", + "nullable": true, + "properties": { + "when": { + "type": "object", + "properties": { + "clauses": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "subspan_clauses": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "trace_clauses": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + } + } + }, + "behavior": { + "type": "string", + "enum": [ + "hidden" + ], + "default": "hidden" + } + }, + "required": [ + "when" + ] + }, + "ProjectScoreConfig": { + "type": "object", + "nullable": true, + "properties": { + "multi_select": { + "type": "boolean", + "nullable": true + }, + "destination": { + "type": "string", + "nullable": true + }, + "visibility": { + "type": "object", + "nullable": true, + "properties": { + "users": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "groups": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + } + } + }, + "online": { + "$ref": "#/components/schemas/OnlineScoreConfig" + }, + "condition": { + "$ref": "#/components/schemas/ProjectScoreCondition" + }, + "object_types": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "enum": [ + "project_logs", + "dataset", + "experiment" + ] + } + } + } + }, + "ProjectScore": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project score" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the project score belongs under" + }, + "user_id": { + "type": "string", + "format": "uuid" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of project score creation" + }, + "name": { + "type": "string", + "description": "Name of the project score" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the project score" + }, + "score_type": { + "$ref": "#/components/schemas/ProjectScoreType" + }, + "categories": { + "$ref": "#/components/schemas/ProjectScoreCategories" + }, + "config": { + "$ref": "#/components/schemas/ProjectScoreConfig" + }, + "position": { + "type": "string", + "nullable": true, + "description": "An optional LexoRank-based string that sets the sort position for the score in the UI" + } + }, + "required": [ + "id", + "project_id", + "user_id", + "name", + "score_type" + ], + "description": "A project score is a user-configured score, which can be manually-labeled through the UI" + }, + "CreateProjectScore": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the project score belongs under" + }, + "name": { + "type": "string", + "description": "Name of the project score" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the project score" + }, + "score_type": { + "$ref": "#/components/schemas/ProjectScoreType" + }, + "categories": { + "$ref": "#/components/schemas/ProjectScoreCategories" + }, + "config": { + "$ref": "#/components/schemas/ProjectScoreConfig" + } + }, + "required": [ + "project_id", + "name", + "score_type" + ], + "description": "A project score is a user-configured score, which can be manually-labeled through the UI" + }, + "PatchProjectScore": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the project score" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the project score" + }, + "score_type": { + "$ref": "#/components/schemas/ProjectScoreType", + "nullable": true + }, + "categories": { + "$ref": "#/components/schemas/ProjectScoreCategories" + }, + "config": { + "$ref": "#/components/schemas/ProjectScoreConfig" + } + }, + "description": "A project score is a user-configured score, which can be manually-labeled through the UI" + }, + "ProjectTag": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project tag" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the project tag belongs under" + }, + "user_id": { + "type": "string", + "format": "uuid" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of project tag creation" + }, + "name": { + "type": "string", + "description": "Name of the project tag" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the project tag" + }, + "color": { + "type": "string", + "nullable": true, + "description": "Color of the tag for the UI" + }, + "position": { + "type": "string", + "nullable": true, + "description": "An optional LexoRank-based string that sets the sort position for the tag in the UI" + } + }, + "required": [ + "id", + "project_id", + "user_id", + "name" + ], + "description": "A project tag is a user-configured tag for tracking and filtering your experiments, logs, and other data" + }, + "CreateProjectTag": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the project tag belongs under" + }, + "name": { + "type": "string", + "description": "Name of the project tag" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the project tag" + }, + "color": { + "type": "string", + "nullable": true, + "description": "Color of the tag for the UI" + } + }, + "required": [ + "project_id", + "name" + ] + }, + "PatchProjectTag": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the project tag" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the project tag" + }, + "color": { + "type": "string", + "nullable": true, + "description": "Color of the tag for the UI" + } + } + }, + "SpanIFrame": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the span iframe" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the span iframe belongs under" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifies the user who created the span iframe" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of span iframe creation" + }, + "deleted_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of span iframe deletion, or null if the span iframe is still active" + }, + "name": { + "type": "string", + "description": "Name of the span iframe" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the span iframe" + }, + "url": { + "type": "string", + "description": "URL to embed the project viewer in an iframe" + }, + "post_message": { + "type": "boolean", + "nullable": true, + "description": "Whether to post messages to the iframe containing the span's data. This is useful when you want to render more data than fits in the URL." + } + }, + "required": [ + "id", + "project_id", + "name", + "url" + ] + }, + "CreateSpanIFrame": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the span iframe belongs under" + }, + "name": { + "type": "string", + "description": "Name of the span iframe" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the span iframe" + }, + "url": { + "type": "string", + "description": "URL to embed the project viewer in an iframe" + }, + "post_message": { + "type": "boolean", + "nullable": true, + "description": "Whether to post messages to the iframe containing the span's data. This is useful when you want to render more data than fits in the URL." + } + }, + "required": [ + "project_id", + "name", + "url" + ] + }, + "PatchSpanIFrame": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the span iframe" + }, + "url": { + "type": "string", + "nullable": true, + "description": "URL to embed the project viewer in an iframe" + }, + "post_message": { + "type": "boolean", + "nullable": true, + "description": "Whether to post messages to the iframe containing the span's data. This is useful when you want to render more data than fits in the URL." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the span iframe" + } + } + }, + "CodeBundle": { + "type": "object", + "properties": { + "runtime_context": { + "type": "object", + "properties": { + "runtime": { + "type": "string", + "enum": [ + "node", + "python", + "browser", + "quickjs" + ] + }, + "version": { + "type": "string" + } + }, + "required": [ + "runtime", + "version" + ] + }, + "location": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "experiment" + ] + }, + "eval_name": { + "type": "string" + }, + "position": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "task" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "scorer" + ] + }, + "index": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "type", + "index" + ], + "title": "scorer" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "classifier" + ] + }, + "index": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "type", + "index" + ], + "title": "classifier" + } + ] + } + }, + "required": [ + "type", + "eval_name", + "position" + ], + "title": "experiment" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "function" + ] + }, + "index": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "type", + "index" + ], + "title": "function" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "sandbox" + ] + }, + "sandbox_spec": { + "oneOf": [ + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "modal" + ] + }, + "snapshot_ref": { + "type": "string", + "description": "sandbox snapshot ref" + } + }, + "required": [ + "provider", + "snapshot_ref" + ] + }, + { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "lambda" + ] + } + }, + "required": [ + "provider" + ] + } + ] + }, + "entrypoints": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Which entrypoints to execute in the sandbox" + }, + "eval_name": { + "type": "string" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "nullable": true + }, + "description": "Parameter values for sandbox eval execution" + }, + "evaluator_definition": { + "nullable": true, + "description": "Definition of current evaluator with parameters" + } + }, + "required": [ + "type", + "sandbox_spec", + "eval_name" + ] + } + ] + }, + "bundle_id": { + "type": "string", + "nullable": true + }, + "preview": { + "type": "string", + "nullable": true, + "description": "A preview of the code" + } + }, + "required": [ + "runtime_context", + "location" + ] + }, + "FunctionIdRef": { + "type": "object", + "properties": {}, + "additionalProperties": { + "nullable": true + }, + "description": "Options for identifying a function" + }, + "PromptBlockData": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "chat" + ] + }, + "messages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatCompletionMessageParam" + } + }, + "tools": { + "type": "string" + } + }, + "required": [ + "type", + "messages" + ], + "title": "chat" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "completion" + ] + }, + "content": { + "type": "string" + } + }, + "required": [ + "type", + "content" + ], + "title": "completion" + } + ] + }, + "GraphNode": { + "anyOf": [ + { + "type": "object", + "properties": { + "description": { + "type": "string", + "nullable": true, + "description": "The description of the node" + }, + "position": { + "type": "object", + "nullable": true, + "properties": { + "x": { + "type": "number", + "description": "The x position of the node" + }, + "y": { + "type": "number", + "description": "The y position of the node" + } + }, + "required": [ + "x", + "y" + ], + "description": "The position of the node" + }, + "type": { + "type": "string", + "enum": [ + "function" + ] + }, + "function": { + "$ref": "#/components/schemas/FunctionIdRef" + } + }, + "required": [ + "type", + "function" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string", + "nullable": true, + "description": "The description of the node" + }, + "position": { + "type": "object", + "nullable": true, + "properties": { + "x": { + "type": "number", + "description": "The x position of the node" + }, + "y": { + "type": "number", + "description": "The y position of the node" + } + }, + "required": [ + "x", + "y" + ], + "description": "The position of the node" + }, + "type": { + "type": "string", + "enum": [ + "input" + ], + "description": "The input to the graph" + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string", + "nullable": true, + "description": "The description of the node" + }, + "position": { + "type": "object", + "nullable": true, + "properties": { + "x": { + "type": "number", + "description": "The x position of the node" + }, + "y": { + "type": "number", + "description": "The y position of the node" + } + }, + "required": [ + "x", + "y" + ], + "description": "The position of the node" + }, + "type": { + "type": "string", + "enum": [ + "output" + ], + "description": "The output of the graph" + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string", + "nullable": true, + "description": "The description of the node" + }, + "position": { + "type": "object", + "nullable": true, + "properties": { + "x": { + "type": "number", + "description": "The x position of the node" + }, + "y": { + "type": "number", + "description": "The y position of the node" + } + }, + "required": [ + "x", + "y" + ], + "description": "The position of the node" + }, + "type": { + "type": "string", + "enum": [ + "literal" + ] + }, + "value": { + "nullable": true, + "description": "A literal value to be returned" + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string", + "nullable": true, + "description": "The description of the node" + }, + "position": { + "type": "object", + "nullable": true, + "properties": { + "x": { + "type": "number", + "description": "The x position of the node" + }, + "y": { + "type": "number", + "description": "The y position of the node" + } + }, + "required": [ + "x", + "y" + ], + "description": "The position of the node" + }, + "type": { + "type": "string", + "enum": [ + "btql" + ] + }, + "expr": { + "type": "string", + "description": "A BTQL expression to be evaluated" + } + }, + "required": [ + "type", + "expr" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string", + "nullable": true, + "description": "The description of the node" + }, + "position": { + "type": "object", + "nullable": true, + "properties": { + "x": { + "type": "number", + "description": "The x position of the node" + }, + "y": { + "type": "number", + "description": "The y position of the node" + } + }, + "required": [ + "x", + "y" + ], + "description": "The position of the node" + }, + "type": { + "type": "string", + "enum": [ + "gate" + ] + }, + "condition": { + "type": "string", + "nullable": true, + "description": "A BTQL expression to be evaluated" + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string", + "nullable": true, + "description": "The description of the node" + }, + "position": { + "type": "object", + "nullable": true, + "properties": { + "x": { + "type": "number", + "description": "The x position of the node" + }, + "y": { + "type": "number", + "description": "The y position of the node" + } + }, + "required": [ + "x", + "y" + ], + "description": "The position of the node" + }, + "type": { + "type": "string", + "enum": [ + "aggregator" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string", + "nullable": true, + "description": "The description of the node" + }, + "position": { + "type": "object", + "nullable": true, + "properties": { + "x": { + "type": "number", + "description": "The x position of the node" + }, + "y": { + "type": "number", + "description": "The y position of the node" + } + }, + "required": [ + "x", + "y" + ], + "description": "The position of the node" + }, + "type": { + "type": "string", + "enum": [ + "prompt_template" + ] + }, + "prompt": { + "$ref": "#/components/schemas/PromptBlockData" + } + }, + "required": [ + "type", + "prompt" + ] + } + ] + }, + "GraphEdge": { + "type": "object", + "properties": { + "source": { + "type": "object", + "properties": { + "node": { + "type": "string", + "maxLength": 1024, + "description": "The id of the node in the graph" + }, + "variable": { + "type": "string" + } + }, + "required": [ + "node", + "variable" + ] + }, + "target": { + "type": "object", + "properties": { + "node": { + "type": "string", + "maxLength": 1024, + "description": "The id of the node in the graph" + }, + "variable": { + "type": "string" + } + }, + "required": [ + "node", + "variable" + ] + }, + "purpose": { + "type": "string", + "enum": [ + "control", + "data", + "messages" + ], + "description": "The purpose of the edge" + } + }, + "required": [ + "source", + "target", + "purpose" + ] + }, + "GraphData": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "graph" + ] + }, + "nodes": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/GraphNode" + } + }, + "edges": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/GraphEdge" + } + } + }, + "required": [ + "type", + "nodes", + "edges" + ], + "description": "This feature is preliminary and unsupported.", + "title": "graph" + }, + "FacetData": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "facet" + ] + }, + "preprocessor": { + "allOf": [ + { + "$ref": "#/components/schemas/NullableSavedFunctionId" + }, + { + "description": "The preprocessor function to use for facet extraction. If not provided, the project default preprocessor will be used, falling back to the global 'thread' preprocessor." + } + ] + }, + "prompt": { + "type": "string", + "description": "The prompt to use for LLM extraction. The preprocessed text will be provided as context." + }, + "model": { + "type": "string", + "description": "The model to use for facet extraction" + }, + "embedding_model": { + "type": "string", + "description": "The embedding model to use for vectorizing facet results." + }, + "no_match_pattern": { + "type": "string", + "description": "Regex pattern to identify outputs that do not match the facet. If the output matches, the facet will be saved as 'no_match'" + } + }, + "required": [ + "type", + "prompt" + ], + "title": "facet" + }, + "TopicMapGenerationSettings": { + "type": "object", + "properties": { + "algorithm": { + "type": "string", + "enum": [ + "hdbscan", + "kmeans" + ] + }, + "dimension_reduction": { + "type": "string", + "enum": [ + "umap", + "pca", + "none" + ] + }, + "sample_size": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "n_clusters": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "min_cluster_size": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "min_samples": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "hierarchy_threshold": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "naming_model": { + "type": "string" + } + }, + "required": [ + "algorithm", + "dimension_reduction" + ], + "description": "Clustering and naming settings used to generate this topic map" + }, + "TopicMapData": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "topic_map" + ] + }, + "source_facet": { + "type": "string", + "description": "The facet field name to use as input for classification" + }, + "embedding_model": { + "type": "string", + "description": "The embedding model to use for embedding facet values" + }, + "bundle_key": { + "type": "string", + "description": "Key of the topic map bundle in code_bundles bucket" + }, + "report_key": { + "type": "string", + "description": "Key of the clustering report in code_bundles bucket" + }, + "topic_names": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Mapping from topic_id to topic name" + }, + "generation_settings": { + "$ref": "#/components/schemas/TopicMapGenerationSettings" + }, + "disable_reconciliation": { + "type": "boolean", + "description": "Whether new topic generation should ignore the previously saved report during reconciliation. Defaults to false when omitted." + }, + "distance_threshold": { + "type": "number", + "description": "Maximum distance to nearest centroid. If exceeded, returns no_match." + }, + "btql_filter": { + "type": "string", + "description": "Per-topic-map BTQL filter that was applied when this version was generated. Absent on versions generated before this was recorded." + }, + "automation_btql_filter": { + "type": "string", + "description": "Automation-level BTQL filter that was applied when this version was generated. Absent on versions generated before this was recorded." + } + }, + "required": [ + "type", + "source_facet", + "embedding_model" + ] + }, + "BatchedFacetData": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "batched_facet" + ] + }, + "preprocessor": { + "allOf": [ + { + "$ref": "#/components/schemas/NullableSavedFunctionId" + }, + { + "description": "The preprocessor function to use for facet extraction. If not provided, the project default preprocessor will be used, falling back to the global 'thread' preprocessor." + } + ] + }, + "facets": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the facet" + }, + "prompt": { + "type": "string", + "description": "The prompt to use for LLM extraction. The preprocessed text will be provided as context." + }, + "model": { + "type": "string", + "description": "The model to use for facet extraction" + }, + "embedding_model": { + "type": "string", + "description": "The embedding model to use for vectorizing facet results." + }, + "no_match_pattern": { + "type": "string", + "description": "Regex pattern to identify outputs that do not match the facet. If the output matches, the facet will be saved as 'no_match'" + } + }, + "required": [ + "name", + "prompt" + ] + } + }, + "topic_maps": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "object", + "properties": { + "function_name": { + "type": "string", + "description": "The name of the topic map function" + }, + "topic_map_id": { + "type": "string", + "description": "The id of the topic map function" + }, + "topic_map_data": { + "$ref": "#/components/schemas/TopicMapData" + } + }, + "required": [ + "function_name", + "topic_map_data" + ] + } + }, + "description": "Topic maps that depend on facets in this batch, keyed by source facet name. Each source facet can have multiple topic maps." + } + }, + "required": [ + "type", + "facets" + ], + "title": "batched_facet" + }, + "FunctionData": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "prompt" + ] + } + }, + "required": [ + "type" + ], + "title": "prompt" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "code" + ] + }, + "data": { + "anyOf": [ + { + "allOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "bundle" + ] + } + }, + "required": [ + "type" + ] + }, + { + "$ref": "#/components/schemas/CodeBundle" + } + ], + "title": "bundle" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "inline" + ] + }, + "runtime_context": { + "type": "object", + "properties": { + "runtime": { + "type": "string", + "enum": [ + "node", + "python", + "browser", + "quickjs" + ] + }, + "version": { + "type": "string" + } + }, + "required": [ + "runtime", + "version" + ] + }, + "code": { + "type": "string" + }, + "code_hash": { + "type": "string", + "description": "SHA256 hash of the code, computed at save time" + } + }, + "required": [ + "type", + "runtime_context", + "code" + ], + "title": "inline" + } + ] + } + }, + "required": [ + "type", + "data" + ], + "title": "code" + }, + { + "$ref": "#/components/schemas/GraphData" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "remote_eval" + ] + }, + "endpoint": { + "type": "string" + }, + "eval_name": { + "type": "string" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "parameters_version": { + "type": "string", + "nullable": true, + "description": "The version (transaction ID) of the parameters being used" + } + }, + "required": [ + "type", + "endpoint", + "eval_name", + "parameters" + ], + "description": "A remote eval to run", + "title": "remote_eval" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "global" + ] + }, + "name": { + "type": "string" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + }, + "config": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Configuration options to pass to the global function (e.g., for preprocessor customization)" + } + }, + "required": [ + "type", + "name" + ], + "title": "global" + }, + { + "$ref": "#/components/schemas/FacetData" + }, + { + "$ref": "#/components/schemas/BatchedFacetData" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "parameters" + ] + }, + "data": { + "type": "object", + "additionalProperties": { + "nullable": true + }, + "description": "The parameters data" + }, + "__schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "object" + ] + }, + "properties": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "nullable": true + } + } + }, + "required": { + "type": "array", + "items": { + "type": "string" + } + }, + "additionalProperties": { + "type": "boolean" + } + }, + "required": [ + "type", + "properties" + ], + "description": "JSON Schema format for parameters" + } + }, + "required": [ + "type", + "data", + "__schema" + ], + "title": "parameters" + }, + { + "allOf": [ + { + "$ref": "#/components/schemas/TopicMapData" + }, + { + "title": "topic_map" + } + ] + } + ] + }, + "Function": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the prompt" + }, + "_xact_id": { + "type": "string", + "description": "The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the prompt (see the `version` parameter)" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the prompt belongs under" + }, + "log_id": { + "type": "string", + "enum": [ + "p" + ], + "description": "A literal 'p' which identifies the object as a project prompt" + }, + "org_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the organization" + }, + "name": { + "type": "string", + "description": "Name of the prompt" + }, + "slug": { + "type": "string", + "description": "Unique identifier for the prompt" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the prompt" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of prompt creation" + }, + "prompt_data": { + "$ref": "#/components/schemas/PromptDataNullish" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the prompt" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "User-controlled metadata about the prompt" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnumNullish" + }, + "function_data": { + "$ref": "#/components/schemas/FunctionData" + }, + "origin": { + "type": "object", + "nullable": true, + "properties": { + "object_type": { + "$ref": "#/components/schemas/AclObjectType" + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "Id of the object the function is originating from" + }, + "internal": { + "type": "boolean", + "nullable": true, + "description": "The function exists for internal purposes and should not be displayed in the list of functions." + } + }, + "required": [ + "object_type", + "object_id" + ] + }, + "function_schema": { + "type": "object", + "nullable": true, + "properties": { + "parameters": { + "nullable": true + }, + "returns": { + "nullable": true + } + }, + "description": "JSON schema for the function's parameters and return type" + } + }, + "required": [ + "id", + "_xact_id", + "project_id", + "log_id", + "org_id", + "name", + "slug", + "function_data" + ] + }, + "CreateFunction": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the prompt belongs under" + }, + "name": { + "type": "string", + "minLength": 1, + "description": "Name of the prompt" + }, + "slug": { + "type": "string", + "minLength": 1, + "description": "Unique identifier for the prompt" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the prompt" + }, + "prompt_data": { + "$ref": "#/components/schemas/PromptDataNullish" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the prompt" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnumNullish" + }, + "function_data": { + "$ref": "#/components/schemas/FunctionData" + }, + "origin": { + "type": "object", + "nullable": true, + "properties": { + "object_type": { + "$ref": "#/components/schemas/AclObjectType" + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "Id of the object the function is originating from" + }, + "internal": { + "type": "boolean", + "nullable": true, + "description": "The function exists for internal purposes and should not be displayed in the list of functions." + } + }, + "required": [ + "object_type", + "object_id" + ] + }, + "function_schema": { + "type": "object", + "nullable": true, + "properties": { + "parameters": { + "nullable": true + }, + "returns": { + "nullable": true + } + }, + "description": "JSON schema for the function's parameters and return type" + } + }, + "required": [ + "project_id", + "name", + "slug", + "function_data" + ] + }, + "FunctionDataNullish": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "prompt" + ] + } + }, + "required": [ + "type" + ], + "title": "prompt" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "code" + ] + }, + "data": { + "anyOf": [ + { + "allOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "bundle" + ] + } + }, + "required": [ + "type" + ] + }, + { + "$ref": "#/components/schemas/CodeBundle" + } + ], + "title": "bundle" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "inline" + ] + }, + "runtime_context": { + "type": "object", + "properties": { + "runtime": { + "type": "string", + "enum": [ + "node", + "python", + "browser", + "quickjs" + ] + }, + "version": { + "type": "string" + } + }, + "required": [ + "runtime", + "version" + ] + }, + "code": { + "type": "string" + }, + "code_hash": { + "type": "string", + "description": "SHA256 hash of the code, computed at save time" + } + }, + "required": [ + "type", + "runtime_context", + "code" + ], + "title": "inline" + } + ] + } + }, + "required": [ + "type", + "data" + ], + "title": "code" + }, + { + "$ref": "#/components/schemas/GraphData" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "remote_eval" + ] + }, + "endpoint": { + "type": "string" + }, + "eval_name": { + "type": "string" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "parameters_version": { + "type": "string", + "nullable": true, + "description": "The version (transaction ID) of the parameters being used" + } + }, + "required": [ + "type", + "endpoint", + "eval_name", + "parameters" + ], + "description": "A remote eval to run", + "title": "remote_eval" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "global" + ] + }, + "name": { + "type": "string" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + }, + "config": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Configuration options to pass to the global function (e.g., for preprocessor customization)" + } + }, + "required": [ + "type", + "name" + ], + "title": "global" + }, + { + "$ref": "#/components/schemas/FacetData" + }, + { + "$ref": "#/components/schemas/BatchedFacetData" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "parameters" + ] + }, + "data": { + "type": "object", + "additionalProperties": { + "nullable": true + }, + "description": "The parameters data" + }, + "__schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "object" + ] + }, + "properties": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "nullable": true + } + } + }, + "required": { + "type": "array", + "items": { + "type": "string" + } + }, + "additionalProperties": { + "type": "boolean" + } + }, + "required": [ + "type", + "properties" + ], + "description": "JSON Schema format for parameters" + } + }, + "required": [ + "type", + "data", + "__schema" + ], + "title": "parameters" + }, + { + "allOf": [ + { + "$ref": "#/components/schemas/TopicMapData" + }, + { + "title": "topic_map" + } + ] + }, + { + "type": "null" + } + ] + }, + "PatchFunction": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the prompt" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the prompt" + }, + "prompt_data": { + "$ref": "#/components/schemas/PromptDataNullish" + }, + "function_data": { + "$ref": "#/components/schemas/FunctionDataNullish" + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "A list of tags for the prompt" + } + } + }, + "InvokeParent": { + "anyOf": [ + { + "type": "object", + "properties": { + "object_type": { + "type": "string", + "enum": [ + "project_logs", + "experiment", + "playground_logs" + ] + }, + "object_id": { + "type": "string", + "description": "The id of the container object you are logging to" + }, + "row_ids": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string", + "description": "The id of the row" + }, + "span_id": { + "type": "string", + "description": "The span_id of the row" + }, + "root_span_id": { + "type": "string", + "description": "The root_span_id of the row" + } + }, + "required": [ + "id", + "span_id", + "root_span_id" + ], + "description": "Identifiers for the row to to log a subspan under" + }, + "propagated_event": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Include these properties in every span created under this parent" + } + }, + "required": [ + "object_type", + "object_id" + ], + "description": "Span parent properties", + "title": "span_parent_struct" + }, + { + "type": "string", + "description": "The parent's span identifier, created by calling `.export()` on a span" + } + ], + "description": "Options for tracing the function call" + }, + "StreamingMode": { + "type": "string", + "nullable": true, + "enum": [ + "auto", + "parallel", + "json", + "text", + null + ], + "description": "The mode format of the returned value (defaults to 'auto')" + }, + "InvokeApi": { + "type": "object", + "properties": { + "input": { + "nullable": true, + "description": "Argument to the function, which can be any JSON serializable value" + }, + "expected": { + "nullable": true, + "description": "The expected output of the function" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Any relevant metadata. This will be logged and available as the `metadata` argument." + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "Any relevant tags to log on the span." + }, + "messages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatCompletionMessageParam" + }, + "description": "If the function is an LLM, additional messages to pass along to it" + }, + "parent": { + "$ref": "#/components/schemas/InvokeParent" + }, + "stream": { + "type": "boolean", + "nullable": true, + "description": "Whether to stream the response. If true, results will be returned in the Braintrust SSE format." + }, + "mode": { + "$ref": "#/components/schemas/StreamingMode" + }, + "strict": { + "type": "boolean", + "nullable": true, + "description": "If true, throw an error if one of the variables in the prompt is not present in the input" + }, + "mcp_auth": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "oauth_token": { + "type": "string", + "description": "The OAuth token to use" + } + } + }, + "description": "Map of MCP server URL to auth credentials" + }, + "overrides": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Partial function definition to merge with the function being invoked. Fields are validated against the function type's schema at runtime. For facets: { preprocessor?, prompt?, model? }. For prompts: { model?, ... }." + }, + "version": { + "type": "string", + "description": "The version of the function" + } + }, + "description": "The request to invoke a function" + }, + "ViewDataSearch": { + "type": "object", + "nullable": true, + "properties": { + "filter": { + "type": "array", + "nullable": true, + "items": { + "nullable": true + } + }, + "tag": { + "type": "array", + "nullable": true, + "items": { + "nullable": true + } + }, + "match": { + "type": "array", + "nullable": true, + "items": { + "nullable": true + } + }, + "sort": { + "type": "array", + "nullable": true, + "items": { + "nullable": true + } + } + } + }, + "ViewData": { + "type": "object", + "nullable": true, + "properties": { + "search": { + "$ref": "#/components/schemas/ViewDataSearch" + }, + "custom_charts": { + "nullable": true + } + }, + "description": "The view definition" + }, + "ViewOptions": { + "anyOf": [ + { + "type": "object", + "properties": { + "viewType": { + "type": "string", + "enum": [ + "monitor" + ] + }, + "options": { + "type": "object", + "properties": { + "spanType": { + "type": "string", + "nullable": true, + "enum": [ + "range", + "frame", + null + ] + }, + "rangeValue": { + "type": "string", + "nullable": true + }, + "frameStart": { + "type": "string", + "nullable": true + }, + "frameEnd": { + "type": "string", + "nullable": true + }, + "tzUTC": { + "type": "boolean", + "nullable": true + }, + "chartVisibility": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "boolean" + } + }, + "projectId": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true, + "enum": [ + "project", + "experiment", + null + ] + }, + "groupBy": { + "type": "string", + "nullable": true + } + } + }, + "freezeColumns": { + "type": "boolean", + "nullable": true + } + }, + "required": [ + "viewType", + "options" + ], + "title": "MonitorViewOptions" + }, + { + "type": "object", + "properties": { + "columnVisibility": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "boolean" + } + }, + "columnOrder": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "columnSizing": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "number" + } + }, + "grouping": { + "type": "string", + "nullable": true + }, + "rowHeight": { + "type": "string", + "nullable": true + }, + "tallGroupRows": { + "type": "boolean", + "nullable": true + }, + "layout": { + "type": "string", + "nullable": true + }, + "topicMapReportKey": { + "type": "string", + "nullable": true + }, + "chartHeight": { + "type": "number", + "nullable": true + }, + "excludedMeasures": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "score", + "metric", + "metadata" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "type", + "value" + ] + } + }, + "yMetric": { + "type": "object", + "nullable": true, + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "score", + "metric", + "metadata" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "type", + "value" + ] + }, + "xAxis": { + "type": "object", + "nullable": true, + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "score", + "metric", + "metadata" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "type", + "value" + ] + }, + "symbolGrouping": { + "type": "object", + "nullable": true, + "properties": { + "type": { + "type": "string", + "enum": [ + "none", + "score", + "metric", + "metadata" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "type", + "value" + ] + }, + "xAxisAggregation": { + "type": "string", + "nullable": true, + "description": "One of 'avg', 'sum', 'min', 'max', 'median', 'all'" + }, + "chartAnnotations": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "text": { + "type": "string" + } + }, + "required": [ + "id", + "text" + ] + } + }, + "timeRangeFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "from": { + "type": "string" + }, + "to": { + "type": "string" + } + }, + "required": [ + "from", + "to" + ] + }, + { + "type": "null" + } + ] + }, + "queryShape": { + "type": "string", + "nullable": true, + "enum": [ + "traces", + "spans", + "topics", + null + ] + }, + "cluster": { + "type": "string", + "nullable": true + }, + "freezeColumns": { + "type": "boolean", + "nullable": true + } + }, + "title": "TableViewOptions" + }, + { + "type": "null" + } + ], + "description": "Options for the view in the app" + }, + "View": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the view" + }, + "object_type": { + "$ref": "#/components/schemas/AclObjectType" + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "The id of the object the view applies to" + }, + "view_type": { + "type": "string", + "enum": [ + "projects", + "experiments", + "experiment", + "playgrounds", + "playground", + "datasets", + "dataset", + "prompts", + "parameters", + "tools", + "scorers", + "classifiers", + "logs", + "monitor", + "for_review_project_log", + "for_review_experiments", + "for_review_datasets", + null + ], + "description": "Type of object that the view corresponds to." + }, + "name": { + "type": "string", + "description": "Name of the view" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of view creation" + }, + "view_data": { + "$ref": "#/components/schemas/ViewData" + }, + "options": { + "$ref": "#/components/schemas/ViewOptions" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifies the user who created the view" + }, + "deleted_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of role deletion, or null if the role is still active" + } + }, + "required": [ + "id", + "object_type", + "object_id", + "view_type", + "name" + ] + }, + "CreateView": { + "type": "object", + "properties": { + "object_type": { + "$ref": "#/components/schemas/AclObjectType" + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "The id of the object the view applies to" + }, + "view_type": { + "type": "string", + "enum": [ + "projects", + "experiments", + "experiment", + "playgrounds", + "playground", + "datasets", + "dataset", + "prompts", + "parameters", + "tools", + "scorers", + "classifiers", + "logs", + "monitor", + "for_review_project_log", + "for_review_experiments", + "for_review_datasets", + null + ], + "description": "Type of object that the view corresponds to." + }, + "name": { + "type": "string", + "description": "Name of the view" + }, + "view_data": { + "$ref": "#/components/schemas/ViewData" + }, + "options": { + "$ref": "#/components/schemas/ViewOptions" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifies the user who created the view" + }, + "deleted_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of role deletion, or null if the role is still active" + } + }, + "required": [ + "object_type", + "object_id", + "view_type", + "name" + ] + }, + "PatchView": { + "type": "object", + "properties": { + "object_type": { + "$ref": "#/components/schemas/AclObjectType" + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "The id of the object the view applies to" + }, + "view_type": { + "type": "string", + "nullable": true, + "enum": [ + "projects", + "experiments", + "experiment", + "playgrounds", + "playground", + "datasets", + "dataset", + "prompts", + "parameters", + "tools", + "scorers", + "classifiers", + "logs", + "monitor", + "for_review_project_log", + "for_review_experiments", + "for_review_datasets", + null + ], + "description": "Type of object that the view corresponds to." + }, + "name": { + "type": "string", + "nullable": true, + "description": "Name of the view" + }, + "view_data": { + "$ref": "#/components/schemas/ViewData" + }, + "options": { + "$ref": "#/components/schemas/ViewOptions" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifies the user who created the view" + } + }, + "required": [ + "object_type", + "object_id" + ] + }, + "DeleteView": { + "type": "object", + "properties": { + "object_type": { + "$ref": "#/components/schemas/AclObjectType" + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "The id of the object the view applies to" + } + }, + "required": [ + "object_type", + "object_id" + ] + }, + "ImageRenderingMode": { + "type": "string", + "nullable": true, + "enum": [ + "auto", + "click_to_load", + "blocked", + null + ], + "description": "Controls how images are rendered in the UI: 'auto' loads images automatically, 'click_to_load' shows a placeholder until clicked, 'blocked' prevents image loading entirely" + }, + "Organization": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the organization" + }, + "name": { + "type": "string", + "description": "Name of the organization" + }, + "api_url": { + "type": "string", + "nullable": true + }, + "is_universal_api": { + "type": "boolean", + "nullable": true + }, + "is_dataplane_private": { + "type": "boolean", + "nullable": true + }, + "proxy_url": { + "type": "string", + "nullable": true + }, + "realtime_url": { + "type": "string", + "nullable": true + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of organization creation" + }, + "image_rendering_mode": { + "$ref": "#/components/schemas/ImageRenderingMode" + } + }, + "required": [ + "id", + "name" + ] + }, + "PatchOrganization": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the organization" + }, + "api_url": { + "type": "string", + "nullable": true + }, + "is_universal_api": { + "type": "boolean", + "nullable": true + }, + "is_dataplane_private": { + "type": "boolean", + "nullable": true + }, + "proxy_url": { + "type": "string", + "nullable": true + }, + "realtime_url": { + "type": "string", + "nullable": true + }, + "image_rendering_mode": { + "$ref": "#/components/schemas/ImageRenderingMode" + } + } + }, + "PatchOrganizationMembersOutput": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ] + }, + "org_id": { + "type": "string", + "description": "The id of the org that was modified." + }, + "send_email_error": { + "type": "string", + "nullable": true, + "description": "If invite emails failed to send for some reason, the patch operation will still complete, but we will return an error message here" + }, + "added_users": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "email": { + "type": "string", + "nullable": true + }, + "api_key": { + "type": "string", + "nullable": true + }, + "token_name": { + "type": "string", + "nullable": true + } + }, + "required": [ + "id" + ] + }, + "description": "If service accounts with tokens were created, this will contain the added users with their API keys" + } + }, + "required": [ + "status", + "org_id" + ] + }, + "PatchOrganizationMembers": { + "type": "object", + "properties": { + "invite_users": { + "type": "object", + "nullable": true, + "properties": { + "ids": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the user" + }, + "description": "Ids of existing users to invite" + }, + "emails": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "Emails of users to invite" + }, + "service_accounts": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "token_name": { + "type": "string", + "nullable": true, + "description": "Optional name of an initial service token to create for the new service account. When this field is set, the request must be authenticated with a service token that has organization-owner permissions, not a user API key." + } + }, + "required": [ + "name" + ] + }, + "description": "Service accounts to create. Any caller permitted to add organization members can create service accounts (but not necessarily their associated tokens)." + }, + "send_invite_emails": { + "type": "boolean", + "nullable": true, + "description": "If true, send invite emails to the users who wore actually added" + }, + "group_ids": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the group" + }, + "description": "Optional list of group ids to add newly-invited users to." + }, + "group_names": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "description": "Name of the group" + }, + "description": "Optional list of group names to add newly-invited users to." + }, + "group_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Singular form of group_ids" + }, + "group_name": { + "type": "string", + "nullable": true, + "description": "Singular form of group_names" + } + }, + "description": "Users to invite to the organization" + }, + "remove_users": { + "type": "object", + "nullable": true, + "properties": { + "ids": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the user" + }, + "description": "Ids of users to remove" + }, + "emails": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "Emails of users to remove" + } + }, + "description": "Users to remove from the organization" + }, + "org_name": { + "type": "string", + "nullable": true, + "description": "For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, or in case you want to explicitly assert the organization you are modifying, you may specify the name of the organization." + }, + "org_id": { + "type": "string", + "nullable": true, + "description": "For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, or in case you want to explicitly assert the organization you are modifying, you may specify the id of the organization." + } + } + }, + "ApiKey": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the api key" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of api key creation" + }, + "name": { + "type": "string", + "description": "Name of the api key" + }, + "preview_name": { + "type": "string" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Unique identifier for the user" + }, + "user_email": { + "type": "string", + "nullable": true, + "description": "The user's email" + }, + "user_given_name": { + "type": "string", + "nullable": true, + "description": "Given name of the user" + }, + "user_family_name": { + "type": "string", + "nullable": true, + "description": "Family name of the user" + }, + "org_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Unique identifier for the organization" + } + }, + "required": [ + "id", + "name", + "preview_name" + ] + }, + "CreateServiceTokenOutput": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the service token" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of service token creation" + }, + "name": { + "type": "string", + "description": "Name of the service token" + }, + "preview_name": { + "type": "string" + }, + "service_account_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Unique identifier for the service token" + }, + "service_account_email": { + "type": "string", + "nullable": true, + "description": "The service account email (not routable)" + }, + "service_account_name": { + "type": "string", + "nullable": true, + "description": "The service account name" + }, + "org_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Unique identifier for the organization" + }, + "key": { + "type": "string", + "description": "The raw service token. It will only be exposed this one time" + } + }, + "required": [ + "id", + "name", + "preview_name", + "key" + ] + }, + "ServiceToken": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the service token" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of service token creation" + }, + "name": { + "type": "string", + "description": "Name of the service token" + }, + "preview_name": { + "type": "string" + }, + "service_account_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Unique identifier for the service token" + }, + "service_account_email": { + "type": "string", + "nullable": true, + "description": "The service account email (not routable)" + }, + "service_account_name": { + "type": "string", + "nullable": true, + "description": "The service account name" + }, + "org_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Unique identifier for the organization" + } + }, + "required": [ + "id", + "name", + "preview_name" + ] + }, + "DeleteServiceToken": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the service token." + } + }, + "required": [ + "id" + ] + }, + "AISecret": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the AI secret" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of AI secret creation" + }, + "updated_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of last AI secret update" + }, + "secret_updated_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of last update to the encrypted secret value itself" + }, + "org_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the organization" + }, + "name": { + "type": "string", + "description": "Name of the AI secret" + }, + "type": { + "type": "string", + "nullable": true + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + } + }, + "secret_updated_by_user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "User id of the last update to the encrypted secret value" + }, + "preview_secret": { + "type": "string", + "nullable": true + } + }, + "required": [ + "id", + "org_id", + "name" + ] + }, + "CreateAISecret": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI secret" + }, + "type": { + "type": "string", + "nullable": true + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + } + }, + "secret": { + "type": "string", + "nullable": true, + "description": "Secret value. If omitted in a PUT request, the existing secret value will be left intact, not replaced with null." + }, + "org_name": { + "type": "string", + "nullable": true, + "description": "For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the AI Secret belongs in." + } + }, + "required": [ + "name" + ] + }, + "DeleteAISecret": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI secret" + }, + "org_name": { + "type": "string", + "nullable": true, + "description": "For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the AI Secret belongs in." + } + }, + "required": [ + "name" + ] + }, + "PatchAISecret": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the AI secret" + }, + "type": { + "type": "string", + "nullable": true + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + } + }, + "secret": { + "type": "string", + "nullable": true + } + } + }, + "EnvVar": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the environment variable" + }, + "object_type": { + "type": "string", + "enum": [ + "organization", + "project", + "function" + ], + "description": "The type of the object the environment variable is scoped for" + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "The id of the object the environment variable is scoped for" + }, + "name": { + "type": "string", + "description": "The name of the environment variable" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of environment variable creation" + }, + "secret_updated_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of last update to the encrypted secret value itself" + }, + "secret_updated_by_user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "User id of the last update to the encrypted secret value" + }, + "used": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date the environment variable was last used" + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Optional metadata associated with the environment variable when managed via the function secrets API" + }, + "preview_secret": { + "type": "string", + "nullable": true, + "description": "Redacted preview of the stored secret value" + }, + "secret_type": { + "type": "string", + "nullable": true, + "description": "Optional classification for the secret (for example, the AI provider name)" + }, + "secret_category": { + "type": "string", + "enum": [ + "env_var", + "ai_provider", + "sandbox_provider" + ], + "default": "env_var", + "description": "The category of the secret: env_var for regular environment variables, ai_provider for AI provider API keys" + } + }, + "required": [ + "id", + "object_type", + "object_id", + "name" + ] + }, + "MCPServer": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the MCP server" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the MCP server belongs under" + }, + "user_id": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "Identifies the user who created the MCP server" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of MCP server creation" + }, + "deleted_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of MCP server deletion, or null if the MCP server is still active" + }, + "name": { + "type": "string", + "description": "Name of the MCP server. Within a project, MCP server names are unique" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the MCP server" + }, + "url": { + "type": "string", + "description": "URL of the MCP server endpoint" + } + }, + "required": [ + "id", + "project_id", + "name", + "url" + ] + }, + "CreateMCPServer": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the project that the MCP server belongs under" + }, + "name": { + "type": "string", + "description": "Name of the MCP server. Within a project, MCP server names are unique" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the MCP server" + }, + "url": { + "type": "string", + "description": "URL of the MCP server endpoint" + } + }, + "required": [ + "project_id", + "name", + "url" + ] + }, + "PatchMCPServer": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the MCP server. Within a project, MCP server names are unique" + }, + "url": { + "type": "string", + "nullable": true, + "description": "URL of the MCP server endpoint" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the MCP server" + } + } + }, + "DatasetSnapshot": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the dataset snapshot" + }, + "dataset_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the dataset that this snapshot belongs to" + }, + "name": { + "type": "string", + "description": "Name of the dataset snapshot" + }, + "description": { + "type": "string", + "nullable": true + }, + "xact_id": { + "type": "string", + "description": "Transaction id of the brainstore version at the time of the snapshot" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of dataset snapshot creation" + } + }, + "required": [ + "id", + "dataset_id", + "name", + "description", + "xact_id", + "created" + ] + }, + "CreateDatasetSnapshot": { + "type": "object", + "properties": { + "dataset_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the dataset that this snapshot belongs to" + }, + "name": { + "type": "string", + "minLength": 1, + "description": "Name of the dataset snapshot" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the dataset snapshot" + }, + "xact_id": { + "type": "string", + "minLength": 1, + "description": "Transaction id of the brainstore version at the time of the snapshot" + } + }, + "required": [ + "dataset_id", + "name", + "xact_id" + ] + }, + "PatchDatasetSnapshot": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the dataset snapshot" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the dataset snapshot" + } + } + }, + "Environment": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the environment" + }, + "org_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the organization that the environment belongs under" + }, + "name": { + "type": "string", + "description": "Name of the environment" + }, + "slug": { + "type": "string", + "description": "A url-friendly, unique identifier for the environment within an organization" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the environment" + }, + "created": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of environment creation" + }, + "deleted_at": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Date of environment deletion, or null if the environment is still active" + } + }, + "required": [ + "id", + "org_id", + "name", + "slug" + ] + }, + "CreateEnvironment": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the environment" + }, + "slug": { + "type": "string", + "description": "A url-friendly, unique identifier for the environment within an organization" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the environment" + }, + "org_name": { + "type": "string", + "nullable": true, + "description": "For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the environment belongs in." + } + }, + "required": [ + "name", + "slug" + ] + }, + "PatchEnvironment": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the environment" + }, + "slug": { + "type": "string", + "nullable": true, + "description": "A url-friendly, unique identifier for the environment within an organization" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Textual description of the environment" + } + } + }, + "CrossObjectInsertResponse": { + "type": "object", + "properties": { + "experiment": { + "type": "object", + "nullable": true, + "additionalProperties": { + "$ref": "#/components/schemas/InsertEventsResponse" + }, + "description": "A mapping from experiment id to row ids for inserted `events`" + }, + "dataset": { + "type": "object", + "nullable": true, + "additionalProperties": { + "$ref": "#/components/schemas/InsertEventsResponse" + }, + "description": "A mapping from dataset id to row ids for inserted `events`" + }, + "project_logs": { + "type": "object", + "nullable": true, + "additionalProperties": { + "$ref": "#/components/schemas/InsertEventsResponse" + }, + "description": "A mapping from project id to row ids for inserted `events`" + } + } + }, + "CrossObjectInsertRequest": { + "type": "object", + "properties": { + "experiment": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "object", + "properties": { + "events": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/InsertExperimentEvent" + }, + "description": "A list of experiment events to insert" + }, + "feedback": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/FeedbackExperimentItem" + }, + "description": "A list of experiment feedback items" + } + } + }, + "description": "A mapping from experiment id to a set of log events and feedback items to insert" + }, + "dataset": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "object", + "properties": { + "events": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/InsertDatasetEvent" + }, + "description": "A list of dataset events to insert" + }, + "feedback": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/FeedbackDatasetItem" + }, + "description": "A list of dataset feedback items" + } + } + }, + "description": "A mapping from dataset id to a set of log events and feedback items to insert" + }, + "project_logs": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "object", + "properties": { + "events": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/InsertProjectLogsEvent" + }, + "description": "A list of project logs events to insert" + }, + "feedback": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/FeedbackProjectLogsItem" + }, + "description": "A list of project logs feedback items" + } + } + }, + "description": "A mapping from project id to a set of log events and feedback items to insert" + } + } + }, + "PromptData": { + "type": "object", + "properties": { + "prompt": { + "$ref": "#/components/schemas/PromptBlockDataNullish" + }, + "options": { + "$ref": "#/components/schemas/PromptOptionsNullish" + }, + "parser": { + "$ref": "#/components/schemas/PromptParserNullish" + }, + "tool_functions": { + "type": "array", + "nullable": true, + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/SavedFunctionId" + }, + { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "function" + ] + }, + "id": { + "type": "string" + }, + "version": { + "type": "string", + "description": "The version of the function" + } + }, + "required": [ + "type", + "id" + ], + "title": "function" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "global" + ] + }, + "name": { + "type": "string" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + } + }, + "required": [ + "type", + "name" + ], + "title": "global" + } + ] + } + ] + } + }, + "template_format": { + "type": "string", + "nullable": true, + "enum": [ + "mustache", + "nunjucks", + "none", + null + ] + }, + "mcp": { + "type": "object", + "nullable": true, + "additionalProperties": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "id" + ] + }, + "id": { + "type": "string", + "format": "uuid" + }, + "is_disabled": { + "type": "boolean" + }, + "enabled_tools": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "If omitted, all tools are enabled" + } + }, + "required": [ + "type", + "id" + ], + "title": "MCP server id. This is used for project-level MCP server definitions." + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "url" + ] + }, + "url": { + "type": "string" + }, + "is_disabled": { + "type": "boolean" + }, + "enabled_tools": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + }, + "description": "If omitted, all tools are enabled" + } + }, + "required": [ + "type", + "url" + ], + "title": "MCP server url. This is used for inline definitions of MCP servers." + } + ] + } + }, + "origin": { + "type": "object", + "nullable": true, + "properties": { + "prompt_id": { + "type": "string" + }, + "project_id": { + "type": "string" + }, + "prompt_version": { + "type": "string" + } + } + } + } + }, + "FunctionId": { + "anyOf": [ + { + "type": "object", + "properties": { + "function_id": { + "type": "string", + "description": "The ID of the function" + }, + "version": { + "type": "string", + "description": "The version of the function" + } + }, + "required": [ + "function_id" + ], + "description": "Function id", + "title": "function_id" + }, + { + "type": "object", + "properties": { + "project_name": { + "type": "string", + "description": "The name of the project containing the function" + }, + "slug": { + "type": "string", + "description": "The slug of the function" + }, + "version": { + "type": "string", + "description": "The version of the function" + } + }, + "required": [ + "project_name", + "slug" + ], + "description": "Project name and slug", + "title": "project_slug" + }, + { + "type": "object", + "properties": { + "global_function": { + "type": "string", + "description": "The name of the global function. Currently, the global namespace includes the functions in autoevals" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + } + }, + "required": [ + "global_function" + ], + "description": "Global function name", + "title": "global_function" + }, + { + "type": "object", + "properties": { + "prompt_session_id": { + "type": "string", + "description": "The ID of the prompt session" + }, + "prompt_session_function_id": { + "type": "string", + "description": "The ID of the function in the prompt session" + }, + "version": { + "type": "string", + "description": "The version of the function" + } + }, + "required": [ + "prompt_session_id", + "prompt_session_function_id" + ], + "description": "Prompt session id", + "title": "prompt_session_id" + }, + { + "type": "object", + "properties": { + "inline_context": { + "type": "object", + "properties": { + "runtime": { + "type": "string", + "enum": [ + "node", + "python", + "browser", + "quickjs" + ] + }, + "version": { + "type": "string" + } + }, + "required": [ + "runtime", + "version" + ] + }, + "code": { + "type": "string", + "description": "The inline code to execute" + }, + "function_type": { + "allOf": [ + { + "$ref": "#/components/schemas/FunctionTypeEnum" + }, + { + "description": "The function type for inline code. Required when invoking inline preprocessors." + } + ] + }, + "name": { + "type": "string", + "nullable": true, + "description": "The name of the inline code function" + } + }, + "required": [ + "inline_context", + "code" + ], + "description": "Inline code function", + "title": "inline_code" + }, + { + "type": "object", + "properties": { + "inline_prompt": { + "$ref": "#/components/schemas/PromptData" + }, + "inline_function": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + }, + "name": { + "type": "string", + "nullable": true, + "description": "The name of the inline function" + } + }, + "required": [ + "inline_function" + ], + "description": "Inline function definition", + "title": "inline_function" + }, + { + "type": "object", + "properties": { + "inline_prompt": { + "$ref": "#/components/schemas/PromptData" + }, + "function_type": { + "$ref": "#/components/schemas/FunctionTypeEnum" + }, + "name": { + "type": "string", + "nullable": true, + "description": "The name of the inline prompt" + } + }, + "required": [ + "inline_prompt" + ], + "description": "Inline prompt definition", + "title": "inline_prompt" + } + ], + "description": "The function to evaluate" + }, + "GitMetadataSettings": { + "type": "object", + "nullable": true, + "properties": { + "collect": { + "type": "string", + "enum": [ + "all", + "none", + "some" + ] + }, + "fields": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "commit", + "branch", + "tag", + "dirty", + "author_name", + "author_email", + "commit_message", + "commit_time", + "git_diff" + ] + } + } + }, + "required": [ + "collect" + ], + "additionalProperties": false, + "description": "Optional settings for collecting git metadata. By default, will collect git metadata fields allowed in org-level settings, excluding diff content unless the org opts in." + }, + "RunEval": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "description": "Unique identifier for the project to run the eval in" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "dataset_id": { + "type": "string" + }, + "dataset_version": { + "type": "string", + "nullable": true, + "description": "The version of the dataset to evaluate" + }, + "dataset_environment": { + "type": "string", + "nullable": true, + "description": "The environment tag that resolves to the dataset version to evaluate" + }, + "_internal_btql": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + } + } + }, + "required": [ + "dataset_id" + ], + "description": "Dataset id", + "title": "dataset_id" + }, + { + "type": "object", + "properties": { + "project_name": { + "type": "string" + }, + "dataset_name": { + "type": "string" + }, + "dataset_version": { + "type": "string", + "nullable": true, + "description": "The version of the dataset to evaluate" + }, + "dataset_environment": { + "type": "string", + "nullable": true, + "description": "The environment tag that resolves to the dataset version to evaluate" + }, + "_internal_btql": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + } + } + }, + "required": [ + "project_name", + "dataset_name" + ], + "description": "Project and dataset name", + "title": "project_dataset_name" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "nullable": true + } + } + }, + "required": [ + "data" + ], + "description": "Dataset rows", + "title": "dataset_rows" + } + ], + "description": "The dataset to use" + }, + "name": { + "type": "string", + "description": "The name of the eval to run when multiple evals available" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "nullable": true + }, + "description": "Values for any parameters used in the eval" + }, + "task": { + "$ref": "#/components/schemas/FunctionId" + }, + "scores": { + "type": "array", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/FunctionId" + }, + { + "description": "Options for identifying a function" + } + ] + }, + "description": "The functions to score the eval on" + }, + "experiment_name": { + "type": "string", + "description": "An optional name for the experiment created by this eval. If it conflicts with an existing experiment, it will be suffixed with a unique identifier." + }, + "metadata": { + "type": "object", + "additionalProperties": { + "nullable": true + }, + "description": "Optional experiment-level metadata to store about the evaluation. You can later use this to slice & dice across experiments." + }, + "parent": { + "allOf": [ + { + "$ref": "#/components/schemas/InvokeParent" + }, + { + "description": "Options for tracing the evaluation" + } + ] + }, + "stream": { + "type": "boolean", + "description": "Whether to stream the results of the eval. If true, the request will return two events: one to indicate the experiment has started, and another upon completion. If false, the request will return the evaluation's summary upon completion." + }, + "trial_count": { + "type": "number", + "nullable": true, + "description": "The number of times to run the evaluator per input. This is useful for evaluating applications that have non-deterministic behavior and gives you both a stronger aggregate measure and a sense of the variance in the results." + }, + "is_public": { + "type": "boolean", + "nullable": true, + "description": "Whether the experiment should be public. Defaults to false." + }, + "timeout": { + "type": "number", + "nullable": true, + "description": "The maximum duration, in milliseconds, to run the evaluation. Defaults to undefined, in which case there is no timeout." + }, + "max_concurrency": { + "type": "number", + "nullable": true, + "default": 10, + "description": "The maximum number of tasks/scorers that will be run concurrently. Defaults to 10. If null is provided, no max concurrency will be used." + }, + "base_experiment_name": { + "type": "string", + "nullable": true, + "description": "An optional experiment name to use as a base. If specified, the new experiment will be summarized and compared to this experiment." + }, + "base_experiment_id": { + "type": "string", + "nullable": true, + "description": "An optional experiment id to use as a base. If specified, the new experiment will be summarized and compared to this experiment." + }, + "git_metadata_settings": { + "$ref": "#/components/schemas/GitMetadataSettings" + }, + "repo_info": { + "allOf": [ + { + "$ref": "#/components/schemas/RepoInfo" + }, + { + "description": "Optionally explicitly specify the git metadata for this experiment. This takes precedence over `gitMetadataSettings` if specified." + } + ] + }, + "strict": { + "type": "boolean", + "nullable": true, + "description": "If true, throw an error if one of the variables in the prompt is not present in the input" + }, + "stop_token": { + "type": "string", + "nullable": true, + "description": "The token to stop the run" + }, + "extra_messages": { + "type": "string", + "description": "A template path of extra messages to append to the conversion. These messages will be appended to the end of the conversation, after the last message." + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional tags that will be added to the experiment." + }, + "mcp_auth": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "oauth_token": { + "type": "string", + "description": "The OAuth token to use" + } + } + } + } + }, + "required": [ + "project_id", + "data", + "task", + "scores" + ] + } + }, + "parameters": { + "ProjectIdParam": { + "schema": { + "$ref": "#/components/schemas/ProjectIdParam" + }, + "required": true, + "description": "Project id", + "name": "project_id", + "in": "path" + }, + "ExperimentIdParam": { + "schema": { + "$ref": "#/components/schemas/ExperimentIdParam" + }, + "required": true, + "description": "Experiment id", + "name": "experiment_id", + "in": "path" + }, + "DatasetIdParam": { + "schema": { + "$ref": "#/components/schemas/DatasetIdParam" + }, + "required": true, + "description": "Dataset id", + "name": "dataset_id", + "in": "path" + }, + "PromptIdParam": { + "schema": { + "$ref": "#/components/schemas/PromptIdParam" + }, + "required": true, + "description": "Prompt id", + "name": "prompt_id", + "in": "path" + }, + "PromptSessionIdParam": { + "schema": { + "$ref": "#/components/schemas/PromptSessionIdParam" + }, + "required": true, + "description": "PromptSession id", + "name": "prompt_session_id", + "in": "path" + }, + "RoleIdParam": { + "schema": { + "$ref": "#/components/schemas/RoleIdParam" + }, + "required": true, + "description": "Role id", + "name": "role_id", + "in": "path" + }, + "GroupIdParam": { + "schema": { + "$ref": "#/components/schemas/GroupIdParam" + }, + "required": true, + "description": "Group id", + "name": "group_id", + "in": "path" + }, + "AclIdParam": { + "schema": { + "$ref": "#/components/schemas/AclIdParam" + }, + "required": true, + "description": "Acl id", + "name": "acl_id", + "in": "path" + }, + "UserIdParam": { + "schema": { + "$ref": "#/components/schemas/UserIdParam" + }, + "required": true, + "description": "User id", + "name": "user_id", + "in": "path" + }, + "AgentIdParam": { + "schema": { + "$ref": "#/components/schemas/AgentIdParam" + }, + "required": true, + "description": "Agent id", + "name": "agent_id", + "in": "path" + }, + "ProjectAutomationIdParam": { + "schema": { + "$ref": "#/components/schemas/ProjectAutomationIdParam" + }, + "required": true, + "description": "ProjectAutomation id", + "name": "project_automation_id", + "in": "path" + }, + "ProjectScoreIdParam": { + "schema": { + "$ref": "#/components/schemas/ProjectScoreIdParam" + }, + "required": true, + "description": "ProjectScore id", + "name": "project_score_id", + "in": "path" + }, + "ProjectTagIdParam": { + "schema": { + "$ref": "#/components/schemas/ProjectTagIdParam" + }, + "required": true, + "description": "ProjectTag id", + "name": "project_tag_id", + "in": "path" + }, + "SpanIframeIdParam": { + "schema": { + "$ref": "#/components/schemas/SpanIframeIdParam" + }, + "required": true, + "description": "SpanIframe id", + "name": "span_iframe_id", + "in": "path" + }, + "FunctionIdParam": { + "schema": { + "$ref": "#/components/schemas/FunctionIdParam" + }, + "required": true, + "description": "Function id", + "name": "function_id", + "in": "path" + }, + "ViewIdParam": { + "schema": { + "$ref": "#/components/schemas/ViewIdParam" + }, + "required": true, + "description": "View id", + "name": "view_id", + "in": "path" + }, + "OrganizationIdParam": { + "schema": { + "$ref": "#/components/schemas/OrganizationIdParam" + }, + "required": true, + "description": "Organization id", + "name": "organization_id", + "in": "path" + }, + "ApiKeyIdParam": { + "schema": { + "$ref": "#/components/schemas/ApiKeyIdParam" + }, + "required": true, + "description": "ApiKey id", + "name": "api_key_id", + "in": "path" + }, + "ServiceTokenIdParam": { + "schema": { + "$ref": "#/components/schemas/ServiceTokenIdParam" + }, + "required": true, + "description": "ServiceToken id", + "name": "service_token_id", + "in": "path" + }, + "AiSecretIdParam": { + "schema": { + "$ref": "#/components/schemas/AiSecretIdParam" + }, + "required": true, + "description": "AiSecret id", + "name": "ai_secret_id", + "in": "path" + }, + "EnvVarIdParam": { + "schema": { + "$ref": "#/components/schemas/EnvVarIdParam" + }, + "required": true, + "description": "EnvVar id", + "name": "env_var_id", + "in": "path" + }, + "McpServerIdParam": { + "schema": { + "$ref": "#/components/schemas/McpServerIdParam" + }, + "required": true, + "description": "McpServer id", + "name": "mcp_server_id", + "in": "path" + }, + "DatasetSnapshotIdParam": { + "schema": { + "$ref": "#/components/schemas/DatasetSnapshotIdParam" + }, + "required": true, + "description": "DatasetSnapshot id", + "name": "dataset_snapshot_id", + "in": "path" + }, + "ProjectIdQuery": { + "schema": { + "$ref": "#/components/schemas/ProjectIdQuery" + }, + "required": false, + "description": "Project id", + "name": "project_id", + "in": "query" + }, + "ProjectName": { + "schema": { + "$ref": "#/components/schemas/ProjectName" + }, + "required": false, + "description": "Name of the project to search for", + "name": "project_name", + "in": "query", + "allowReserved": true + }, + "ExperimentName": { + "schema": { + "$ref": "#/components/schemas/ExperimentName" + }, + "required": false, + "description": "Name of the experiment to search for", + "name": "experiment_name", + "in": "query", + "allowReserved": true + }, + "DatasetName": { + "schema": { + "$ref": "#/components/schemas/DatasetName" + }, + "required": false, + "description": "Name of the dataset to search for", + "name": "dataset_name", + "in": "query", + "allowReserved": true + }, + "PromptName": { + "schema": { + "$ref": "#/components/schemas/PromptName" + }, + "required": false, + "description": "Name of the prompt to search for", + "name": "prompt_name", + "in": "query", + "allowReserved": true + }, + "PromptSessionName": { + "schema": { + "$ref": "#/components/schemas/PromptSessionName" + }, + "required": false, + "description": "Name of the prompt_session to search for", + "name": "prompt_session_name", + "in": "query", + "allowReserved": true + }, + "RoleName": { + "schema": { + "$ref": "#/components/schemas/RoleName" + }, + "required": false, + "description": "Name of the role to search for", + "name": "role_name", + "in": "query", + "allowReserved": true + }, + "GroupName": { + "schema": { + "$ref": "#/components/schemas/GroupName" + }, + "required": false, + "description": "Name of the group to search for", + "name": "group_name", + "in": "query", + "allowReserved": true + }, + "AgentName": { + "schema": { + "$ref": "#/components/schemas/AgentName" + }, + "required": false, + "description": "Name of the agent to search for", + "name": "agent_name", + "in": "query", + "allowReserved": true + }, + "ProjectAutomationName": { + "schema": { + "$ref": "#/components/schemas/ProjectAutomationName" + }, + "required": false, + "description": "Name of the project_automation to search for", + "name": "project_automation_name", + "in": "query", + "allowReserved": true + }, + "ProjectScoreName": { + "schema": { + "$ref": "#/components/schemas/ProjectScoreName" + }, + "required": false, + "description": "Name of the project_score to search for", + "name": "project_score_name", + "in": "query", + "allowReserved": true + }, + "ProjectTagName": { + "schema": { + "$ref": "#/components/schemas/ProjectTagName" + }, + "required": false, + "description": "Name of the project_tag to search for", + "name": "project_tag_name", + "in": "query", + "allowReserved": true + }, + "SpanIframeName": { + "schema": { + "$ref": "#/components/schemas/SpanIframeName" + }, + "required": false, + "description": "Name of the span_iframe to search for", + "name": "span_iframe_name", + "in": "query", + "allowReserved": true + }, + "FunctionName": { + "schema": { + "$ref": "#/components/schemas/FunctionName" + }, + "required": false, + "description": "Name of the function to search for", + "name": "function_name", + "in": "query", + "allowReserved": true + }, + "ViewName": { + "schema": { + "$ref": "#/components/schemas/ViewName" + }, + "required": false, + "description": "Name of the view to search for", + "name": "view_name", + "in": "query", + "allowReserved": true + }, + "ApiKeyName": { + "schema": { + "$ref": "#/components/schemas/ApiKeyName" + }, + "required": false, + "description": "Name of the api_key to search for", + "name": "api_key_name", + "in": "query", + "allowReserved": true + }, + "ServiceTokenName": { + "schema": { + "$ref": "#/components/schemas/ServiceTokenName" + }, + "required": false, + "description": "Name of the service_token to search for", + "name": "service_token_name", + "in": "query", + "allowReserved": true + }, + "AiSecretName": { + "schema": { + "$ref": "#/components/schemas/AiSecretName" + }, + "required": false, + "description": "Name of the ai_secret to search for", + "name": "ai_secret_name", + "in": "query", + "allowReserved": true + }, + "EnvVarName": { + "schema": { + "$ref": "#/components/schemas/EnvVarName" + }, + "required": false, + "description": "Name of the env_var to search for", + "name": "env_var_name", + "in": "query", + "allowReserved": true + }, + "McpServerName": { + "schema": { + "$ref": "#/components/schemas/McpServerName" + }, + "required": false, + "description": "Name of the mcp_server to search for", + "name": "mcp_server_name", + "in": "query", + "allowReserved": true + }, + "DatasetSnapshotName": { + "schema": { + "$ref": "#/components/schemas/DatasetSnapshotName" + }, + "required": false, + "description": "Name of the dataset_snapshot to search for", + "name": "dataset_snapshot_name", + "in": "query", + "allowReserved": true + }, + "OrgName": { + "schema": { + "$ref": "#/components/schemas/OrgName" + }, + "required": false, + "description": "Filter search results to within a particular organization", + "name": "org_name", + "in": "query", + "allowReserved": true + }, + "Ids": { + "schema": { + "$ref": "#/components/schemas/Ids" + }, + "required": false, + "description": "Filter search results to a particular set of object IDs. To specify a list of IDs, include the query param multiple times", + "name": "ids", + "in": "query" + }, + "AppLimitParam": { + "schema": { + "$ref": "#/components/schemas/AppLimitParam" + }, + "required": false, + "description": "Limit the number of objects to return", + "name": "limit", + "in": "query" + }, + "AppLimitWithDefaultParam": { + "schema": { + "$ref": "#/components/schemas/AppLimitWithDefaultParam" + }, + "required": false, + "description": "Limit the number of objects to return", + "name": "limit", + "in": "query" + }, + "FetchLimitParam": { + "schema": { + "$ref": "#/components/schemas/FetchLimitParam" + }, + "required": false, + "description": "limit the number of traces fetched\n\nFetch queries may be paginated if the total result size is expected to be large (e.g. project_logs which accumulate over a long time). Note that fetch queries only support pagination in descending time order (from latest to earliest `_xact_id`. Furthermore, later pages may return rows which showed up in earlier pages, except with an earlier `_xact_id`. This happens because pagination occurs over the whole version history of the event log. You will most likely want to exclude any such duplicate, outdated rows (by `id`) from your combined result set.\n\nThe `limit` parameter controls the number of full traces to return. So you may end up with more individual rows than the specified limit if you are fetching events containing traces.", + "name": "limit", + "in": "query" + }, + "StartingAfter": { + "schema": { + "$ref": "#/components/schemas/StartingAfter" + }, + "required": false, + "description": "Pagination cursor id.\n\nFor example, if the final item in the last page you fetched had an id of `foo`, pass `starting_after=foo` to fetch the next page. Note: you may only pass one of `starting_after` and `ending_before`", + "name": "starting_after", + "in": "query" + }, + "EndingBefore": { + "schema": { + "$ref": "#/components/schemas/EndingBefore" + }, + "required": false, + "description": "Pagination cursor id.\n\nFor example, if the initial item in the last page you fetched had an id of `foo`, pass `ending_before=foo` to fetch the previous page. Note: you may only pass one of `starting_after` and `ending_before`", + "name": "ending_before", + "in": "query" + }, + "MaxXactId": { + "schema": { + "$ref": "#/components/schemas/MaxXactId" + }, + "required": false, + "description": "DEPRECATION NOTICE: The manually-constructed pagination cursor is deprecated in favor of the explicit 'cursor' returned by object fetch requests. Please prefer the 'cursor' argument going forwards.\n\nTogether, `max_xact_id` and `max_root_span_id` form a pagination cursor\n\nSince a paginated fetch query returns results in order from latest to earliest, the cursor for the next page can be found as the row with the minimum (earliest) value of the tuple `(_xact_id, root_span_id)`. See the documentation of `limit` for an overview of paginating fetch queries.", + "name": "max_xact_id", + "in": "query" + }, + "MaxRootSpanId": { + "schema": { + "$ref": "#/components/schemas/MaxRootSpanId" + }, + "required": false, + "description": "DEPRECATION NOTICE: The manually-constructed pagination cursor is deprecated in favor of the explicit 'cursor' returned by object fetch requests. Please prefer the 'cursor' argument going forwards.\n\nTogether, `max_xact_id` and `max_root_span_id` form a pagination cursor\n\nSince a paginated fetch query returns results in order from latest to earliest, the cursor for the next page can be found as the row with the minimum (earliest) value of the tuple `(_xact_id, root_span_id)`. See the documentation of `limit` for an overview of paginating fetch queries.", + "name": "max_root_span_id", + "in": "query" + }, + "Version": { + "schema": { + "$ref": "#/components/schemas/Version" + }, + "required": false, + "description": "Retrieve a snapshot of events from a past time\n\nThe version id is essentially a filter on the latest event transaction id. You can use the `max_xact_id` returned by a past fetch as the version to reproduce that exact fetch.", + "name": "version", + "in": "query" + }, + "PromptVersion": { + "schema": { + "$ref": "#/components/schemas/PromptVersion" + }, + "required": false, + "description": "Retrieve prompt at a specific version.\n\nThe version id can either be a transaction id (e.g. '1000192656880881099') or a version identifier (e.g. '81cd05ee665fdfb3').", + "name": "version", + "in": "query" + }, + "PromptEnvironment": { + "schema": { + "$ref": "#/components/schemas/PromptEnvironment" + }, + "required": false, + "description": "Filter by environment slug. Cannot be used together with `version`.\n\nFor `GET /v1/prompt`, environment resolution currently requires the request to match a single prompt. If multiple prompts match, the endpoint returns `400` (for example when `limit=1` is not set). Use `limit=1` or other filters (for example `slug`, `project_id`) to narrow results.", + "name": "environment", + "in": "query", + "allowReserved": true + }, + "SummarizeScores": { + "schema": { + "$ref": "#/components/schemas/SummarizeScores" + }, + "required": false, + "description": "Whether to summarize the scores and metrics. If false (or omitted), only the metadata will be returned.", + "name": "summarize_scores", + "in": "query" + }, + "ComparisonExperimentId": { + "schema": { + "$ref": "#/components/schemas/ComparisonExperimentId" + }, + "required": false, + "description": "The experiment to compare against, if summarizing scores and metrics. If omitted, will fall back to the `base_exp_id` stored in the experiment metadata, and then to the most recent experiment run in the same project. Must pass `summarize_scores=true` for this id to be used", + "name": "comparison_experiment_id", + "in": "query" + }, + "SummarizeData": { + "schema": { + "$ref": "#/components/schemas/SummarizeData" + }, + "required": false, + "description": "Whether to summarize the data. If false (or omitted), only the metadata will be returned.", + "name": "summarize_data", + "in": "query" + }, + "Slug": { + "schema": { + "$ref": "#/components/schemas/Slug" + }, + "required": false, + "description": "Retrieve prompt with a specific slug", + "name": "slug", + "in": "query", + "allowReserved": true + }, + "ViewType": { + "schema": { + "$ref": "#/components/schemas/ViewType" + }, + "required": false, + "description": "Type of object that the view corresponds to.", + "name": "view_type", + "in": "query" + }, + "UserGivenName": { + "schema": { + "$ref": "#/components/schemas/UserGivenName" + }, + "required": false, + "description": "Given name of the user to search for. You may pass the param multiple times to filter for more than one given name", + "name": "given_name", + "in": "query", + "allowReserved": true + }, + "UserFamilyName": { + "schema": { + "$ref": "#/components/schemas/UserFamilyName" + }, + "required": false, + "description": "Family name of the user to search for. You may pass the param multiple times to filter for more than one family name", + "name": "family_name", + "in": "query", + "allowReserved": true + }, + "UserEmail": { + "schema": { + "$ref": "#/components/schemas/UserEmail" + }, + "required": false, + "description": "Email of the user to search for. You may pass the param multiple times to filter for more than one email", + "name": "email", + "in": "query", + "allowReserved": true + }, + "AclObjectType": { + "schema": { + "$ref": "#/components/schemas/AclObjectType" + }, + "required": true, + "description": "The object type that the ACL applies to", + "name": "object_type", + "in": "query" + }, + "AclObjectId": { + "schema": { + "$ref": "#/components/schemas/AclObjectId" + }, + "required": true, + "description": "The id of the object the ACL applies to", + "name": "object_id", + "in": "query" + }, + "AclListOrgObjectType": { + "schema": { + "$ref": "#/components/schemas/AclListOrgObjectType" + }, + "required": false, + "description": "The object type that the ACL applies to", + "name": "object_type", + "in": "query" + }, + "AclListOrgObjectId": { + "schema": { + "$ref": "#/components/schemas/AclListOrgObjectId" + }, + "required": false, + "description": "The id of the object the ACL applies to", + "name": "object_id", + "in": "query" + }, + "AclListUserId": { + "schema": { + "$ref": "#/components/schemas/AclListUserId" + }, + "required": false, + "description": "Id of the user the ACL applies to. Exactly one of `user_id` and `group_id` will be provided", + "name": "user_id", + "in": "query" + }, + "AclListGroupId": { + "schema": { + "$ref": "#/components/schemas/AclListGroupId" + }, + "required": false, + "description": "Id of the group the ACL applies to. Exactly one of `user_id` and `group_id` will be provided", + "name": "group_id", + "in": "query" + }, + "AclListPermission": { + "schema": { + "$ref": "#/components/schemas/AclListPermission" + }, + "required": false, + "description": "Each permission permits a certain type of operation on an object in the system\n\nPermissions can be assigned to to objects on an individual basis, or grouped into roles", + "name": "permission", + "in": "query" + }, + "AclListRestrictObjectType": { + "schema": { + "$ref": "#/components/schemas/AclListRestrictObjectType" + }, + "required": false, + "description": "The object type that the ACL applies to", + "name": "restrict_object_type", + "in": "query" + }, + "AclListRoleId": { + "schema": { + "$ref": "#/components/schemas/AclListRoleId" + }, + "required": false, + "description": "Id of the role the ACL grants. Exactly one of `permission` and `role_id` will be provided", + "name": "role_id", + "in": "query" + }, + "ProjectScoreType": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/ProjectScoreType" + }, + { + "type": "array", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/ProjectScoreType" + }, + { + "title": "project_score_type" + } + ] + } + } + ] + }, + "required": false, + "name": "score_type", + "in": "query" + }, + "AISecretType": { + "schema": { + "$ref": "#/components/schemas/AISecretType" + }, + "required": false, + "name": "ai_secret_type", + "in": "query" + }, + "EnvVarObjectType": { + "schema": { + "$ref": "#/components/schemas/EnvVarObjectType" + }, + "required": false, + "description": "The type of the object the environment variable is scoped for", + "name": "object_type", + "in": "query" + }, + "EnvVarObjectId": { + "schema": { + "$ref": "#/components/schemas/EnvVarObjectId" + }, + "required": false, + "description": "The id of the object the environment variable is scoped for", + "name": "object_id", + "in": "query" + } + } + }, + "paths": { + "/v1/project": { + "post": { + "tags": [ + "Projects" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postProject", + "description": "Create a new project. If there is an existing project with the same name as the one specified in the request, will return the existing project unmodified", + "summary": "Create project", + "requestBody": { + "description": "Any desired information about the new project object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateProject" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new project object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Project" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getProject", + "tags": [ + "Projects" + ], + "description": "List out all projects. The projects are sorted by creation date, with the most recently-created projects coming first", + "summary": "List projects", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/ProjectName" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of project objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Project" + }, + "description": "A list of project objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProject", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/project`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/project/{project_id}": { + "get": { + "operationId": "getProjectId", + "tags": [ + "Projects" + ], + "description": "Get a project object by its id", + "summary": "Get project", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the project object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Project" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchProjectId", + "tags": [ + "Projects" + ], + "description": "Partially update a project object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update project", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchProject" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the project object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Project" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteProjectId", + "tags": [ + "Projects" + ], + "description": "Delete a project object by its id", + "summary": "Delete project", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted project object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Project" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProjectId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/project/{project_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/project_logs/{project_id}/insert": { + "post": { + "operationId": "postProjectLogsIdInsert", + "tags": [ + "Logs" + ], + "description": "Insert a set of events into the project logs", + "summary": "Insert project logs events", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectIdParam" + } + ], + "requestBody": { + "description": "An array of project logs events to insert", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsertProjectLogsEventRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the inserted row ids", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsertEventsResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProjectLogsIdInsert", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/project_logs/{project_id}/insert`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/project_logs/{project_id}/fetch": { + "post": { + "operationId": "postProjectLogsIdFetch", + "tags": [ + "Logs" + ], + "description": "Fetch the events in a project logs. Equivalent to the GET form of the same path, but with the parameters in the request body rather than in the URL query. For more complex queries, use the `POST /btql` endpoint.", + "summary": "Fetch project logs (POST form)", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectIdParam" + } + ], + "requestBody": { + "description": "Filters for the fetch query", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FetchEventsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the fetched rows", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FetchProjectLogsEventsResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getProjectLogsIdFetch", + "tags": [ + "Logs" + ], + "description": "Fetch the events in a project logs. Equivalent to the POST form of the same path, but with the parameters in the URL query rather than in the request body. For more complex queries, use the `POST /btql` endpoint.", + "summary": "Fetch project logs (GET form)", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectIdParam" + }, + { + "$ref": "#/components/parameters/FetchLimitParam" + }, + { + "$ref": "#/components/parameters/MaxXactId" + }, + { + "$ref": "#/components/parameters/MaxRootSpanId" + }, + { + "$ref": "#/components/parameters/Version" + } + ], + "responses": { + "200": { + "description": "Returns the fetched rows", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FetchProjectLogsEventsResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProjectLogsIdFetch", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/project_logs/{project_id}/fetch`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/project_logs/{project_id}/feedback": { + "post": { + "operationId": "postProjectLogsIdFeedback", + "tags": [ + "Logs" + ], + "description": "Log feedback for a set of project logs events", + "summary": "Feedback for project logs events", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectIdParam" + } + ], + "requestBody": { + "description": "An array of feedback objects", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FeedbackProjectLogsEventRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Returns a success status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FeedbackResponseSchema" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProjectLogsIdFeedback", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/project_logs/{project_id}/feedback`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/experiment": { + "post": { + "tags": [ + "Experiments" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postExperiment", + "description": "Create a new experiment. If there is an existing experiment in the project with the same name as the one specified in the request, will return the existing experiment unmodified", + "summary": "Create experiment", + "requestBody": { + "description": "Any desired information about the new experiment object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateExperiment" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new experiment object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Experiment" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getExperiment", + "tags": [ + "Experiments" + ], + "description": "List out all experiments. The experiments are sorted by creation date, with the most recently-created experiments coming first", + "summary": "List experiments", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitWithDefaultParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/ExperimentName" + }, + { + "$ref": "#/components/parameters/ProjectName" + }, + { + "$ref": "#/components/parameters/ProjectIdQuery" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of experiment objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Experiment" + }, + "description": "A list of experiment objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsExperiment", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/experiment`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/experiment/{experiment_id}": { + "get": { + "operationId": "getExperimentId", + "tags": [ + "Experiments" + ], + "description": "Get an experiment object by its id", + "summary": "Get experiment", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the experiment object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Experiment" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchExperimentId", + "tags": [ + "Experiments" + ], + "description": "Partially update an experiment object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update experiment", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchExperiment" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the experiment object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Experiment" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteExperimentId", + "tags": [ + "Experiments" + ], + "description": "Delete an experiment object by its id", + "summary": "Delete experiment", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted experiment object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Experiment" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsExperimentId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/experiment/{experiment_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/experiment/{experiment_id}/insert": { + "post": { + "operationId": "postExperimentIdInsert", + "tags": [ + "Experiments" + ], + "description": "Insert a set of events into the experiment", + "summary": "Insert experiment events", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + } + ], + "requestBody": { + "description": "An array of experiment events to insert", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsertExperimentEventRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the inserted row ids", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsertEventsResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsExperimentIdInsert", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/experiment/{experiment_id}/insert`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/experiment/{experiment_id}/fetch": { + "post": { + "operationId": "postExperimentIdFetch", + "tags": [ + "Experiments" + ], + "description": "Fetch the events in an experiment. Equivalent to the GET form of the same path, but with the parameters in the request body rather than in the URL query. For more complex queries, use the `POST /btql` endpoint.", + "summary": "Fetch experiment (POST form)", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + } + ], + "requestBody": { + "description": "Filters for the fetch query", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FetchEventsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the fetched rows", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FetchExperimentEventsResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getExperimentIdFetch", + "tags": [ + "Experiments" + ], + "description": "Fetch the events in an experiment. Equivalent to the POST form of the same path, but with the parameters in the URL query rather than in the request body. For more complex queries, use the `POST /btql` endpoint.", + "summary": "Fetch experiment (GET form)", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + }, + { + "$ref": "#/components/parameters/FetchLimitParam" + }, + { + "$ref": "#/components/parameters/MaxXactId" + }, + { + "$ref": "#/components/parameters/MaxRootSpanId" + }, + { + "$ref": "#/components/parameters/Version" + } + ], + "responses": { + "200": { + "description": "Returns the fetched rows", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FetchExperimentEventsResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsExperimentIdFetch", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/experiment/{experiment_id}/fetch`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/experiment/{experiment_id}/feedback": { + "post": { + "operationId": "postExperimentIdFeedback", + "tags": [ + "Experiments" + ], + "description": "Log feedback for a set of experiment events", + "summary": "Feedback for experiment events", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + } + ], + "requestBody": { + "description": "An array of feedback objects", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FeedbackExperimentEventRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Returns a success status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FeedbackResponseSchema" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsExperimentIdFeedback", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/experiment/{experiment_id}/feedback`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/experiment/{experiment_id}/summarize": { + "get": { + "operationId": "getExperimentIdSummarize", + "tags": [ + "Experiments" + ], + "description": "Summarize experiment", + "summary": "Summarize experiment", + "security": [ + { + "bearerAuth": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + }, + { + "$ref": "#/components/parameters/SummarizeScores" + }, + { + "$ref": "#/components/parameters/ComparisonExperimentId" + } + ], + "responses": { + "200": { + "description": "Experiment summary", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SummarizeExperimentResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsExperimentIdSummarize", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/experiment/{experiment_id}/summarize`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ExperimentIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/dataset": { + "post": { + "tags": [ + "Datasets" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postDataset", + "description": "Create a new dataset. If there is an existing dataset in the project with the same name as the one specified in the request, will return the existing dataset unmodified", + "summary": "Create dataset", + "requestBody": { + "description": "Any desired information about the new dataset object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateDataset" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new dataset object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Dataset" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getDataset", + "tags": [ + "Datasets" + ], + "description": "List out all datasets. The datasets are sorted by creation date, with the most recently-created datasets coming first", + "summary": "List datasets", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/DatasetName" + }, + { + "$ref": "#/components/parameters/ProjectName" + }, + { + "$ref": "#/components/parameters/ProjectIdQuery" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of dataset objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Dataset" + }, + "description": "A list of dataset objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsDataset", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/dataset`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/dataset/{dataset_id}": { + "get": { + "operationId": "getDatasetId", + "tags": [ + "Datasets" + ], + "description": "Get a dataset object by its id", + "summary": "Get dataset", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the dataset object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Dataset" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchDatasetId", + "tags": [ + "Datasets" + ], + "description": "Partially update a dataset object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update dataset", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchDataset" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the dataset object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Dataset" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteDatasetId", + "tags": [ + "Datasets" + ], + "description": "Delete a dataset object by its id", + "summary": "Delete dataset", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted dataset object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Dataset" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsDatasetId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/dataset/{dataset_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/dataset/{dataset_id}/insert": { + "post": { + "operationId": "postDatasetIdInsert", + "tags": [ + "Datasets" + ], + "description": "Insert a set of events into the dataset", + "summary": "Insert dataset events", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + } + ], + "requestBody": { + "description": "An array of dataset events to insert", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsertDatasetEventRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the inserted row ids", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsertEventsResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsDatasetIdInsert", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/dataset/{dataset_id}/insert`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/dataset/{dataset_id}/fetch": { + "post": { + "operationId": "postDatasetIdFetch", + "tags": [ + "Datasets" + ], + "description": "Fetch the events in a dataset. Equivalent to the GET form of the same path, but with the parameters in the request body rather than in the URL query. For more complex queries, use the `POST /btql` endpoint.", + "summary": "Fetch dataset (POST form)", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + } + ], + "requestBody": { + "description": "Filters for the fetch query", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FetchEventsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the fetched rows", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FetchDatasetEventsResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getDatasetIdFetch", + "tags": [ + "Datasets" + ], + "description": "Fetch the events in a dataset. Equivalent to the POST form of the same path, but with the parameters in the URL query rather than in the request body. For more complex queries, use the `POST /btql` endpoint.", + "summary": "Fetch dataset (GET form)", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + }, + { + "$ref": "#/components/parameters/FetchLimitParam" + }, + { + "$ref": "#/components/parameters/MaxXactId" + }, + { + "$ref": "#/components/parameters/MaxRootSpanId" + }, + { + "$ref": "#/components/parameters/Version" + } + ], + "responses": { + "200": { + "description": "Returns the fetched rows", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FetchDatasetEventsResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsDatasetIdFetch", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/dataset/{dataset_id}/fetch`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/dataset/{dataset_id}/feedback": { + "post": { + "operationId": "postDatasetIdFeedback", + "tags": [ + "Datasets" + ], + "description": "Log feedback for a set of dataset events", + "summary": "Feedback for dataset events", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + } + ], + "requestBody": { + "description": "An array of feedback objects", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FeedbackDatasetEventRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Returns a success status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FeedbackResponseSchema" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsDatasetIdFeedback", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/dataset/{dataset_id}/feedback`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/dataset/{dataset_id}/summarize": { + "get": { + "operationId": "getDatasetIdSummarize", + "tags": [ + "Datasets" + ], + "description": "Summarize dataset", + "summary": "Summarize dataset", + "security": [ + { + "bearerAuth": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + }, + { + "$ref": "#/components/parameters/SummarizeData" + } + ], + "responses": { + "200": { + "description": "Dataset summary", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SummarizeDatasetResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsDatasetIdSummarize", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/dataset/{dataset_id}/summarize`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/prompt": { + "post": { + "tags": [ + "Prompts" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postPrompt", + "description": "Create a new prompt. If there is an existing prompt in the project with the same slug as the one specified in the request, will return the existing prompt unmodified", + "summary": "Create prompt", + "requestBody": { + "description": "Any desired information about the new prompt object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreatePrompt" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new prompt object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Prompt" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "Prompts" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putPrompt", + "description": "Create or replace prompt. If there is an existing prompt in the project with the same slug as the one specified in the request, will replace the existing prompt with the provided fields", + "summary": "Create or replace prompt", + "requestBody": { + "description": "Any desired information about the new prompt object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreatePrompt" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new prompt object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Prompt" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getPrompt", + "tags": [ + "Prompts" + ], + "description": "List out all prompts. The prompts are sorted by creation date, with the most recently-created prompts coming first", + "summary": "List prompts", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/PromptName" + }, + { + "$ref": "#/components/parameters/ProjectName" + }, + { + "$ref": "#/components/parameters/ProjectIdQuery" + }, + { + "$ref": "#/components/parameters/Slug" + }, + { + "$ref": "#/components/parameters/PromptVersion" + }, + { + "$ref": "#/components/parameters/PromptEnvironment" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of prompt objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Prompt" + }, + "description": "A list of prompt objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsPrompt", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/prompt`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/prompt/{prompt_id}": { + "get": { + "operationId": "getPromptId", + "tags": [ + "Prompts" + ], + "description": "Get a prompt object by its id", + "summary": "Get prompt", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/PromptIdParam" + }, + { + "$ref": "#/components/parameters/PromptVersion" + }, + { + "$ref": "#/components/parameters/PromptEnvironment" + } + ], + "responses": { + "200": { + "description": "Returns the prompt object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Prompt" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchPromptId", + "tags": [ + "Prompts" + ], + "description": "Partially update a prompt object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update prompt", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/PromptIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchPrompt" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the prompt object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Prompt" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deletePromptId", + "tags": [ + "Prompts" + ], + "description": "Delete a prompt object by its id", + "summary": "Delete prompt", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/PromptIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted prompt object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Prompt" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsPromptId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/prompt/{prompt_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/PromptIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/role": { + "post": { + "tags": [ + "Roles" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postRole", + "description": "Create a new role. If there is an existing role with the same name as the one specified in the request, will return the existing role unmodified", + "summary": "Create role", + "requestBody": { + "description": "Any desired information about the new role object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateRole" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new role object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Role" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "Roles" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putRole", + "description": "Create or replace role. If there is an existing role with the same name as the one specified in the request, will replace the existing role with the provided fields", + "summary": "Create or replace role", + "requestBody": { + "description": "Any desired information about the new role object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateRole" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new role object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Role" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getRole", + "tags": [ + "Roles" + ], + "description": "List out all roles. The roles are sorted by creation date, with the most recently-created roles coming first", + "summary": "List roles", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/RoleName" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of role objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Role" + }, + "description": "A list of role objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsRole", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/role`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/role/{role_id}": { + "get": { + "operationId": "getRoleId", + "tags": [ + "Roles" + ], + "description": "Get a role object by its id", + "summary": "Get role", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/RoleIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the role object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Role" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchRoleId", + "tags": [ + "Roles" + ], + "description": "Partially update a role object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update role", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/RoleIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchRole" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the role object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Role" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteRoleId", + "tags": [ + "Roles" + ], + "description": "Delete a role object by its id", + "summary": "Delete role", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/RoleIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted role object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Role" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsRoleId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/role/{role_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/RoleIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/group": { + "post": { + "tags": [ + "Groups" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postGroup", + "description": "Create a new group. If there is an existing group with the same name as the one specified in the request, will return the existing group unmodified", + "summary": "Create group", + "requestBody": { + "description": "Any desired information about the new group object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGroup" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new group object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Group" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "Groups" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putGroup", + "description": "Create or replace group. If there is an existing group with the same name as the one specified in the request, will replace the existing group with the provided fields", + "summary": "Create or replace group", + "requestBody": { + "description": "Any desired information about the new group object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGroup" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new group object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Group" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getGroup", + "tags": [ + "Groups" + ], + "description": "List out all groups. The groups are sorted by creation date, with the most recently-created groups coming first", + "summary": "List groups", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/GroupName" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of group objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Group" + }, + "description": "A list of group objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsGroup", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/group`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/group/{group_id}": { + "get": { + "operationId": "getGroupId", + "tags": [ + "Groups" + ], + "description": "Get a group object by its id", + "summary": "Get group", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/GroupIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the group object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Group" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchGroupId", + "tags": [ + "Groups" + ], + "description": "Partially update a group object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update group", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/GroupIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchGroup" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the group object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Group" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteGroupId", + "tags": [ + "Groups" + ], + "description": "Delete a group object by its id", + "summary": "Delete group", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/GroupIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted group object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Group" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsGroupId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/group/{group_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/GroupIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/acl": { + "post": { + "tags": [ + "Acls" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postAcl", + "description": "Create a new acl. If there is an existing acl with the same contents as the one specified in the request, will return the existing acl unmodified", + "summary": "Create acl", + "requestBody": { + "description": "Any desired information about the new acl object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AclItem" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new acl object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Acl" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getAcl", + "tags": [ + "Acls" + ], + "description": "List out all acls. The acls are sorted by creation date, with the most recently-created acls coming first", + "summary": "List acls", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/AclObjectType" + }, + { + "$ref": "#/components/parameters/AclObjectId" + }, + { + "$ref": "#/components/parameters/AclListUserId" + }, + { + "$ref": "#/components/parameters/AclListGroupId" + }, + { + "$ref": "#/components/parameters/AclListPermission" + }, + { + "$ref": "#/components/parameters/AclListRestrictObjectType" + }, + { + "$ref": "#/components/parameters/AclListRoleId" + } + ], + "responses": { + "200": { + "description": "Returns a list of acl objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Acl" + }, + "description": "A list of acl objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsAcl", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/acl`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/acl/{acl_id}": { + "get": { + "operationId": "getAclId", + "tags": [ + "Acls" + ], + "description": "Get an acl object by its id", + "summary": "Get acl", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AclIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the acl object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Acl" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteAclId", + "tags": [ + "Acls" + ], + "description": "Delete an acl object by its id", + "summary": "Delete acl", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AclIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted acl object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Acl" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsAclId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/acl/{acl_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/AclIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/acl/batch_update": { + "post": { + "operationId": "aclBatchUpdate", + "tags": [ + "Acls" + ], + "description": "Batch update acls. This operation is idempotent, so adding acls which already exist will have no effect, and removing acls which do not exist will have no effect.", + "summary": "Batch update acls", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "description": "Acls to add/remove.", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AclBatchUpdateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "A success status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AclBatchUpdateResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/acl/list_org": { + "get": { + "operationId": "aclListOrg", + "tags": [ + "Acls" + ], + "description": "List all acls in the org. This query requires the caller to have `read_acls` permission at the organization level", + "summary": "List org acls", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/AclListOrgObjectType" + }, + { + "$ref": "#/components/parameters/AclListOrgObjectId" + }, + { + "$ref": "#/components/parameters/AclListUserId" + }, + { + "$ref": "#/components/parameters/AclListGroupId" + }, + { + "$ref": "#/components/parameters/AclListPermission" + }, + { + "$ref": "#/components/parameters/AclListRestrictObjectType" + }, + { + "$ref": "#/components/parameters/AclListRoleId" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "A list of acls", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Acl" + } + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsAclListOrg", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/acl/list_org`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/acl/acl/batch_update": { + "options": { + "operationId": "optionsAclBatchUpdate", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/acl/acl/batch_update`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/user": { + "get": { + "operationId": "getUser", + "tags": [ + "Users" + ], + "description": "List out all users. The users are sorted by creation date, with the most recently-created users coming first", + "summary": "List users", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/UserGivenName" + }, + { + "$ref": "#/components/parameters/UserFamilyName" + }, + { + "$ref": "#/components/parameters/UserEmail" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of user objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + }, + "description": "A list of user objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsUser", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/user`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/user/{user_id}": { + "get": { + "operationId": "getUserId", + "tags": [ + "Users" + ], + "description": "Get a user object by its id", + "summary": "Get user", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/UserIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the user object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsUserId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/user/{user_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/UserIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/agent": { + "post": { + "tags": [ + "Agents" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postAgent", + "description": "Create a new agent. If there is an existing agent with the same name as the one specified in the request, will return the existing agent unmodified", + "summary": "Create agent", + "requestBody": { + "description": "Any desired information about the new agent object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateAgent" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new agent object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Agent" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "Agents" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putAgent", + "description": "Create or replace agent. If there is an existing agent with the same name as the one specified in the request, will replace the existing agent with the provided fields", + "summary": "Create or replace agent", + "requestBody": { + "description": "Any desired information about the new agent object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateAgent" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new agent object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Agent" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getAgent", + "tags": [ + "Agents" + ], + "description": "List out all agents. The agents are sorted by creation date, with the most recently-created agents coming first", + "summary": "List agents", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/AgentName" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of agent objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Agent" + }, + "description": "A list of agent objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsAgent", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/agent`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/agent/{agent_id}": { + "get": { + "operationId": "getAgentId", + "tags": [ + "Agents" + ], + "description": "Get a agent object by its id", + "summary": "Get agent", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AgentIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the agent object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Agent" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchAgentId", + "tags": [ + "Agents" + ], + "description": "Partially update a agent object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update agent", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AgentIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchAgent" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the agent object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Agent" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteAgentId", + "tags": [ + "Agents" + ], + "description": "Delete a agent object by its id", + "summary": "Delete agent", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AgentIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted agent object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Agent" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsAgentId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/agent/{agent_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/AgentIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/project_automation": { + "post": { + "tags": [ + "ProjectAutomations" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postProjectAutomation", + "description": "Create a new project_automation. If there is an existing project_automation with the same name as the one specified in the request, will return the existing project_automation unmodified", + "summary": "Create project_automation", + "requestBody": { + "description": "Any desired information about the new project_automation object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateProjectAutomation" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new project_automation object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectAutomation" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "ProjectAutomations" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putProjectAutomation", + "description": "Create or replace project_automation. If there is an existing project_automation with the same name as the one specified in the request, will replace the existing project_automation with the provided fields", + "summary": "Create or replace project_automation", + "requestBody": { + "description": "Any desired information about the new project_automation object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateProjectAutomation" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new project_automation object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectAutomation" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getProjectAutomation", + "tags": [ + "ProjectAutomations" + ], + "description": "List out all project_automations. The project_automations are sorted by creation date, with the most recently-created project_automations coming first", + "summary": "List project_automations", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/ProjectAutomationName" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of project_automation objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectAutomation" + }, + "description": "A list of project_automation objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProjectAutomation", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/project_automation`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/project_automation/{project_automation_id}": { + "get": { + "operationId": "getProjectAutomationId", + "tags": [ + "ProjectAutomations" + ], + "description": "Get a project_automation object by its id", + "summary": "Get project_automation", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectAutomationIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the project_automation object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectAutomation" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchProjectAutomationId", + "tags": [ + "ProjectAutomations" + ], + "description": "Partially update a project_automation object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update project_automation", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectAutomationIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchProjectAutomation" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the project_automation object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectAutomation" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteProjectAutomationId", + "tags": [ + "ProjectAutomations" + ], + "description": "Delete a project_automation object by its id", + "summary": "Delete project_automation", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectAutomationIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted project_automation object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectAutomation" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProjectAutomationId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/project_automation/{project_automation_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectAutomationIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/project_score": { + "post": { + "tags": [ + "ProjectScores" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postProjectScore", + "description": "Create a new project_score. If there is an existing project_score in the project with the same name as the one specified in the request, will return the existing project_score unmodified", + "summary": "Create project_score", + "requestBody": { + "description": "Any desired information about the new project_score object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateProjectScore" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new project_score object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectScore" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "ProjectScores" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putProjectScore", + "description": "Create or replace project_score. If there is an existing project_score in the project with the same name as the one specified in the request, will replace the existing project_score with the provided fields", + "summary": "Create or replace project_score", + "requestBody": { + "description": "Any desired information about the new project_score object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateProjectScore" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new project_score object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectScore" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getProjectScore", + "tags": [ + "ProjectScores" + ], + "description": "List out all project_scores. The project_scores are sorted by creation date, with the most recently-created project_scores coming first", + "summary": "List project_scores", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/ProjectScoreName" + }, + { + "$ref": "#/components/parameters/ProjectName" + }, + { + "$ref": "#/components/parameters/ProjectIdQuery" + }, + { + "$ref": "#/components/parameters/OrgName" + }, + { + "$ref": "#/components/parameters/ProjectScoreType" + } + ], + "responses": { + "200": { + "description": "Returns a list of project_score objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectScore" + }, + "description": "A list of project_score objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProjectScore", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/project_score`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/project_score/{project_score_id}": { + "get": { + "operationId": "getProjectScoreId", + "tags": [ + "ProjectScores" + ], + "description": "Get a project_score object by its id", + "summary": "Get project_score", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectScoreIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the project_score object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectScore" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchProjectScoreId", + "tags": [ + "ProjectScores" + ], + "description": "Partially update a project_score object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update project_score", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectScoreIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchProjectScore" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the project_score object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectScore" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteProjectScoreId", + "tags": [ + "ProjectScores" + ], + "description": "Delete a project_score object by its id", + "summary": "Delete project_score", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectScoreIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted project_score object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectScore" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProjectScoreId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/project_score/{project_score_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectScoreIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/project_tag": { + "post": { + "tags": [ + "ProjectTags" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postProjectTag", + "description": "Create a new project_tag. If there is an existing project_tag in the project with the same name as the one specified in the request, will return the existing project_tag unmodified", + "summary": "Create project_tag", + "requestBody": { + "description": "Any desired information about the new project_tag object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateProjectTag" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new project_tag object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectTag" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "ProjectTags" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putProjectTag", + "description": "Create or replace project_tag. If there is an existing project_tag in the project with the same name as the one specified in the request, will replace the existing project_tag with the provided fields", + "summary": "Create or replace project_tag", + "requestBody": { + "description": "Any desired information about the new project_tag object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateProjectTag" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new project_tag object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectTag" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getProjectTag", + "tags": [ + "ProjectTags" + ], + "description": "List out all project_tags. The project_tags are sorted by creation date, with the most recently-created project_tags coming first", + "summary": "List project_tags", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/ProjectTagName" + }, + { + "$ref": "#/components/parameters/ProjectName" + }, + { + "$ref": "#/components/parameters/ProjectIdQuery" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of project_tag objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectTag" + }, + "description": "A list of project_tag objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProjectTag", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/project_tag`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/project_tag/{project_tag_id}": { + "get": { + "operationId": "getProjectTagId", + "tags": [ + "ProjectTags" + ], + "description": "Get a project_tag object by its id", + "summary": "Get project_tag", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectTagIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the project_tag object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectTag" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchProjectTagId", + "tags": [ + "ProjectTags" + ], + "description": "Partially update a project_tag object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update project_tag", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectTagIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchProjectTag" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the project_tag object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectTag" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteProjectTagId", + "tags": [ + "ProjectTags" + ], + "description": "Delete a project_tag object by its id", + "summary": "Delete project_tag", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectTagIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted project_tag object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectTag" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProjectTagId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/project_tag/{project_tag_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ProjectTagIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/span_iframe": { + "post": { + "tags": [ + "SpanIframes" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postSpanIframe", + "description": "Create a new span_iframe. If there is an existing span_iframe with the same name as the one specified in the request, will return the existing span_iframe unmodified", + "summary": "Create span_iframe", + "requestBody": { + "description": "Any desired information about the new span_iframe object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSpanIFrame" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new span_iframe object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpanIFrame" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "SpanIframes" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putSpanIframe", + "description": "Create or replace span_iframe. If there is an existing span_iframe with the same name as the one specified in the request, will replace the existing span_iframe with the provided fields", + "summary": "Create or replace span_iframe", + "requestBody": { + "description": "Any desired information about the new span_iframe object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSpanIFrame" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new span_iframe object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpanIFrame" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getSpanIframe", + "tags": [ + "SpanIframes" + ], + "description": "List out all span_iframes. The span_iframes are sorted by creation date, with the most recently-created span_iframes coming first", + "summary": "List span_iframes", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/SpanIframeName" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of span_iframe objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpanIFrame" + }, + "description": "A list of span_iframe objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsSpanIframe", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/span_iframe`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/span_iframe/{span_iframe_id}": { + "get": { + "operationId": "getSpanIframeId", + "tags": [ + "SpanIframes" + ], + "description": "Get a span_iframe object by its id", + "summary": "Get span_iframe", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/SpanIframeIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the span_iframe object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpanIFrame" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchSpanIframeId", + "tags": [ + "SpanIframes" + ], + "description": "Partially update a span_iframe object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update span_iframe", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/SpanIframeIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchSpanIFrame" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the span_iframe object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpanIFrame" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteSpanIframeId", + "tags": [ + "SpanIframes" + ], + "description": "Delete a span_iframe object by its id", + "summary": "Delete span_iframe", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/SpanIframeIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted span_iframe object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpanIFrame" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsSpanIframeId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/span_iframe/{span_iframe_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/SpanIframeIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/function": { + "post": { + "tags": [ + "Functions" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postFunction", + "description": "Create a new function. If there is an existing function in the project with the same slug as the one specified in the request, will return the existing function unmodified", + "summary": "Create function", + "requestBody": { + "description": "Any desired information about the new function object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateFunction" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new function object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Function" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "Functions" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putFunction", + "description": "Create or replace function. If there is an existing function in the project with the same slug as the one specified in the request, will replace the existing function with the provided fields", + "summary": "Create or replace function", + "requestBody": { + "description": "Any desired information about the new function object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateFunction" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new function object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Function" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getFunction", + "tags": [ + "Functions" + ], + "description": "List out all functions. The functions are sorted by creation date, with the most recently-created functions coming first", + "summary": "List functions", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/FunctionName" + }, + { + "$ref": "#/components/parameters/ProjectName" + }, + { + "$ref": "#/components/parameters/ProjectIdQuery" + }, + { + "$ref": "#/components/parameters/Slug" + }, + { + "$ref": "#/components/parameters/PromptVersion" + }, + { + "$ref": "#/components/parameters/PromptEnvironment" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of function objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Function" + }, + "description": "A list of function objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsFunction", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/function`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/function/{function_id}": { + "get": { + "operationId": "getFunctionId", + "tags": [ + "Functions" + ], + "description": "Get a function object by its id", + "summary": "Get function", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/FunctionIdParam" + }, + { + "$ref": "#/components/parameters/PromptVersion" + }, + { + "$ref": "#/components/parameters/PromptEnvironment" + } + ], + "responses": { + "200": { + "description": "Returns the function object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Function" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchFunctionId", + "tags": [ + "Functions" + ], + "description": "Partially update a function object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update function", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/FunctionIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchFunction" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the function object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Function" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteFunctionId", + "tags": [ + "Functions" + ], + "description": "Delete a function object by its id", + "summary": "Delete function", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/FunctionIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted function object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Function" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsFunctionId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/function/{function_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/FunctionIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/function/{function_id}/invoke": { + "post": { + "operationId": "postFunctionIdInvoke", + "tags": [ + "Functions" + ], + "description": "Invoke a function.", + "summary": "Invoke function", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/FunctionIdParam" + } + ], + "requestBody": { + "description": "Function invocation parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvokeApi" + } + } + } + }, + "responses": { + "200": { + "description": "Function invocation response", + "content": { + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsFunctionIdInvoke", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/function/{function_id}/invoke`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/FunctionIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/view": { + "post": { + "tags": [ + "Views" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postView", + "description": "Create a new view. If there is an existing view with the same name as the one specified in the request, will return the existing view unmodified", + "summary": "Create view", + "requestBody": { + "description": "Any desired information about the new view object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateView" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new view object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "Views" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putView", + "description": "Create or replace view. If there is an existing view with the same name as the one specified in the request, will replace the existing view with the provided fields", + "summary": "Create or replace view", + "requestBody": { + "description": "Any desired information about the new view object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateView" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new view object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getView", + "tags": [ + "Views" + ], + "description": "List out all views. The views are sorted by creation date, with the most recently-created views coming first", + "summary": "List views", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/ViewName" + }, + { + "$ref": "#/components/parameters/ViewType" + }, + { + "$ref": "#/components/parameters/AclObjectType" + }, + { + "$ref": "#/components/parameters/AclObjectId" + } + ], + "responses": { + "200": { + "description": "Returns a list of view objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/View" + }, + "description": "A list of view objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsView", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/view`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/view/{view_id}": { + "get": { + "operationId": "getViewId", + "tags": [ + "Views" + ], + "description": "Get a view object by its id", + "summary": "Get view", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ViewIdParam" + }, + { + "$ref": "#/components/parameters/AclObjectType" + }, + { + "$ref": "#/components/parameters/AclObjectId" + } + ], + "responses": { + "200": { + "description": "Returns the view object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchViewId", + "tags": [ + "Views" + ], + "description": "Partially update a view object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update view", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ViewIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchView" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the view object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteViewId", + "tags": [ + "Views" + ], + "description": "Delete a view object by its id", + "summary": "Delete view", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ViewIdParam" + } + ], + "requestBody": { + "description": "Additional parameters for the delete operation", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteView" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the deleted view object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsViewId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/view/{view_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ViewIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/organization": { + "get": { + "operationId": "getOrganization", + "tags": [ + "Organizations" + ], + "description": "List out all organizations. The organizations are sorted by creation date, with the most recently-created organizations coming first", + "summary": "List organizations", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of organization objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Organization" + }, + "description": "A list of organization objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsOrganization", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/organization`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/organization/{organization_id}": { + "get": { + "operationId": "getOrganizationId", + "tags": [ + "Organizations" + ], + "description": "Get an organization object by its id", + "summary": "Get organization", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the organization object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Organization" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchOrganizationId", + "tags": [ + "Organizations" + ], + "description": "Partially update an organization object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update organization", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchOrganization" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the organization object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Organization" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsOrganizationId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/organization/{organization_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/organization/members": { + "patch": { + "operationId": "patchOrganizationMembers", + "tags": [ + "Organizations" + ], + "description": "Add or remove members, create service accounts.", + "summary": "Modify organization membership", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "description": "Members to add/remove", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchOrganizationMembers" + } + } + } + }, + "responses": { + "200": { + "description": "A success status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchOrganizationMembersOutput" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsOrganizationMembers", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/organization/members`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/api_key": { + "get": { + "operationId": "getApiKey", + "tags": [ + "ApiKeys" + ], + "description": "List out all API keys. They are sorted by creation date, with the most recently-created keys coming first.\n\nTo create new API keys, visit [**Settings > API keys**](https://www.braintrust.dev/app/~/configuration/org/api-keys) in the Braintrust UI.", + "summary": "List api_keys", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/ApiKeyName" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of api_key objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApiKey" + }, + "description": "A list of api_key objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsApiKey", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/api_key`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/api_key/{api_key_id}": { + "get": { + "operationId": "getApiKeyId", + "tags": [ + "ApiKeys" + ], + "description": "Get an api_key object by its id", + "summary": "Get api_key", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ApiKeyIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the api_key object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiKey" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteApiKeyId", + "tags": [ + "ApiKeys" + ], + "description": "Delete an api_key object by its id", + "summary": "Delete api_key", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ApiKeyIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted api_key object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiKey" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsApiKeyId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/api_key/{api_key_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ApiKeyIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/service_token": { + "post": { + "tags": [ + "ServiceTokens" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postServiceToken", + "description": "Create a new service token.\n\nWhen calling this endpoint, you must authenticate using a service token that has organization-owner permissions. User API keys cannot be used.", + "summary": "Create service_token", + "requestBody": { + "description": "Any desired information about the new service_token object", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the service token. Does not have to be unique" + }, + "org_name": { + "type": "string", + "nullable": true, + "description": "For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the Service token belongs in." + }, + "service_account_id": { + "type": "string", + "description": "The ID of the service account to which the token should belong. To create a service account, visit [**Settings > Service tokens**](https://www.braintrust.dev/app/~/configuration/org/service-tokens) in the Braintrust UI or call [`PATCH /v1/organization/members`](https://www.braintrust.dev/docs/api-reference/organizations/modify-organization-membership)." + } + }, + "required": [ + "name", + "service_account_id" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Returns an object containing the raw service token. This is the only time the raw API key will be exposed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateServiceTokenOutput" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "ServiceTokens" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putServiceToken", + "description": "Create or replace service_token. If there is an existing service_token with the same name as the one specified in the request, will replace the existing service_token with the provided fields", + "summary": "Create or replace service_token", + "requestBody": { + "description": "Any desired information about the new service_token object", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the service token. Does not have to be unique" + }, + "org_name": { + "type": "string", + "nullable": true, + "description": "For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the Service token belongs in." + }, + "service_account_id": { + "type": "string", + "description": "The ID of the service account to which the token should belong. To create a service account, visit [**Settings > Service tokens**](https://www.braintrust.dev/app/~/configuration/org/service-tokens) in the Braintrust UI or call [`PATCH /v1/organization/members`](https://www.braintrust.dev/docs/api-reference/organizations/modify-organization-membership)." + } + }, + "required": [ + "name", + "service_account_id" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Returns an object containing the raw service token. This is the only time the raw API key will be exposed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateServiceTokenOutput" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getServiceToken", + "tags": [ + "ServiceTokens" + ], + "description": "List out all service tokens. They are sorted by creation date, with the most recently-created tokens coming first.\n\nTo create a service token, visit [**Settings > Service tokens**](https://www.braintrust.dev/app/~/configuration/org/service-tokens) as an organization owner, or call [`POST /v1/service_token`](https://www.braintrust.dev/docs/api-reference/servicetokens/create-service_token) and authenticate with a service token that has organization-owner permissions.", + "summary": "List service_tokens", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/ServiceTokenName" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of service_token objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ServiceToken" + }, + "description": "A list of service_token objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsServiceToken", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/service_token`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/service_token/{service_token_id}": { + "get": { + "operationId": "getServiceTokenId", + "tags": [ + "ServiceTokens" + ], + "description": "Get a service_token object by its id", + "summary": "Get service_token", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ServiceTokenIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the service_token object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceToken" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteServiceTokenId", + "tags": [ + "ServiceTokens" + ], + "description": "Delete a service_token object by its id", + "summary": "Delete service_token", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/ServiceTokenIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted service_token object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceToken" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsServiceTokenId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/service_token/{service_token_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/ServiceTokenIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/ai_secret": { + "post": { + "tags": [ + "AiSecrets" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postAiSecret", + "description": "Create a new ai_secret. If there is an existing ai_secret with the same name as the one specified in the request, will return the existing ai_secret unmodified", + "summary": "Create ai_secret", + "requestBody": { + "description": "Any desired information about the new ai_secret object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateAISecret" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new ai_secret object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISecret" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "AiSecrets" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putAiSecret", + "description": "Create or replace ai_secret. If there is an existing ai_secret with the same name as the one specified in the request, will replace the existing ai_secret with the provided fields", + "summary": "Create or replace ai_secret", + "requestBody": { + "description": "Any desired information about the new ai_secret object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateAISecret" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new ai_secret object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISecret" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getAiSecret", + "tags": [ + "AiSecrets" + ], + "description": "List out all ai_secrets. The ai_secrets are sorted by creation date, with the most recently-created ai_secrets coming first", + "summary": "List ai_secrets", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/AiSecretName" + }, + { + "$ref": "#/components/parameters/OrgName" + }, + { + "$ref": "#/components/parameters/AISecretType" + } + ], + "responses": { + "200": { + "description": "Returns a list of ai_secret objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AISecret" + }, + "description": "A list of ai_secret objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsAiSecret", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/ai_secret`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/ai_secret/{ai_secret_id}": { + "get": { + "operationId": "getAiSecretId", + "tags": [ + "AiSecrets" + ], + "description": "Get an ai_secret object by its id", + "summary": "Get ai_secret", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AiSecretIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the ai_secret object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISecret" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchAiSecretId", + "tags": [ + "AiSecrets" + ], + "description": "Partially update an ai_secret object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update ai_secret", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AiSecretIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchAISecret" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the ai_secret object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISecret" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteAiSecretId", + "tags": [ + "AiSecrets" + ], + "description": "Delete an ai_secret object by its id", + "summary": "Delete ai_secret", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AiSecretIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted ai_secret object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AISecret" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsAiSecretId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/ai_secret/{ai_secret_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/AiSecretIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/env_var": { + "post": { + "tags": [ + "EnvVars" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postEnvVar", + "description": "Create a new env_var. If there is an existing env_var with the same name as the one specified in the request, will return the existing env_var unmodified", + "summary": "Create env_var", + "requestBody": { + "description": "Any desired information about the new env_var object", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "object_type": { + "type": "string", + "enum": [ + "organization", + "project", + "function" + ], + "description": "The type of the object the environment variable is scoped for" + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "The id of the object the environment variable is scoped for" + }, + "name": { + "type": "string", + "description": "The name of the environment variable" + }, + "value": { + "type": "string", + "nullable": true, + "description": "The value of the environment variable. Will be encrypted at rest." + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Optional metadata associated with the environment variable when managed via the function secrets API" + }, + "secret_type": { + "type": "string", + "nullable": true, + "description": "Optional classification for the secret (for example, the AI provider name)" + } + }, + "required": [ + "object_type", + "object_id", + "name" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new env_var object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvVar" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "EnvVars" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putEnvVar", + "description": "Create or replace env_var. If there is an existing env_var with the same name as the one specified in the request, will replace the existing env_var with the provided fields", + "summary": "Create or replace env_var", + "requestBody": { + "description": "Any desired information about the new env_var object", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "object_type": { + "type": "string", + "enum": [ + "organization", + "project", + "function" + ], + "description": "The type of the object the environment variable is scoped for" + }, + "object_id": { + "type": "string", + "format": "uuid", + "description": "The id of the object the environment variable is scoped for" + }, + "name": { + "type": "string", + "description": "The name of the environment variable" + }, + "value": { + "type": "string", + "nullable": true, + "description": "The value of the environment variable. Will be encrypted at rest." + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Optional metadata associated with the environment variable when managed via the function secrets API" + }, + "secret_type": { + "type": "string", + "nullable": true, + "description": "Optional classification for the secret (for example, the AI provider name)" + } + }, + "required": [ + "object_type", + "object_id", + "name" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new env_var object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvVar" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getEnvVar", + "tags": [ + "EnvVars" + ], + "description": "List out all env_vars. The env_vars are sorted by creation date, with the most recently-created env_vars coming first", + "summary": "List env_vars", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/EnvVarName" + }, + { + "$ref": "#/components/parameters/EnvVarObjectType" + }, + { + "$ref": "#/components/parameters/EnvVarObjectId" + } + ], + "responses": { + "200": { + "description": "Returns a list of env_var objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnvVar" + }, + "description": "A list of env_var objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsEnvVar", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/env_var`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/env_var/{env_var_id}": { + "get": { + "operationId": "getEnvVarId", + "tags": [ + "EnvVars" + ], + "description": "Get an env_var object by its id", + "summary": "Get env_var", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/EnvVarIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the env_var object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvVar" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchEnvVarId", + "tags": [ + "EnvVars" + ], + "description": "Partially update an env_var object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update env_var", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/EnvVarIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the environment variable" + }, + "value": { + "type": "string", + "nullable": true, + "description": "The value of the environment variable. Will be encrypted at rest." + }, + "metadata": { + "type": "object", + "nullable": true, + "additionalProperties": { + "nullable": true + }, + "description": "Optional metadata associated with the environment variable when managed via the function secrets API" + }, + "secret_type": { + "type": "string", + "nullable": true, + "description": "Optional classification for the secret (for example, the AI provider name)" + } + }, + "required": [ + "name" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Returns the env_var object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvVar" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteEnvVarId", + "tags": [ + "EnvVars" + ], + "description": "Delete an env_var object by its id", + "summary": "Delete env_var", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/EnvVarIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted env_var object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvVar" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsEnvVarId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/env_var/{env_var_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/EnvVarIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/mcp_server": { + "post": { + "tags": [ + "McpServers" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postMcpServer", + "description": "Create a new mcp_server. If there is an existing mcp_server with the same name as the one specified in the request, will return the existing mcp_server unmodified", + "summary": "Create mcp_server", + "requestBody": { + "description": "Any desired information about the new mcp_server object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateMCPServer" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new mcp_server object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPServer" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "McpServers" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putMcpServer", + "description": "Create or replace mcp_server. If there is an existing mcp_server with the same name as the one specified in the request, will replace the existing mcp_server with the provided fields", + "summary": "Create or replace mcp_server", + "requestBody": { + "description": "Any desired information about the new mcp_server object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateMCPServer" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new mcp_server object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPServer" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getMcpServer", + "tags": [ + "McpServers" + ], + "description": "List out all mcp_servers. The mcp_servers are sorted by creation date, with the most recently-created mcp_servers coming first", + "summary": "List mcp_servers", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/McpServerName" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of mcp_server objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MCPServer" + }, + "description": "A list of mcp_server objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsMcpServer", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/mcp_server`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/mcp_server/{mcp_server_id}": { + "get": { + "operationId": "getMcpServerId", + "tags": [ + "McpServers" + ], + "description": "Get a mcp_server object by its id", + "summary": "Get mcp_server", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/McpServerIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the mcp_server object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPServer" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchMcpServerId", + "tags": [ + "McpServers" + ], + "description": "Partially update a mcp_server object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update mcp_server", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/McpServerIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchMCPServer" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the mcp_server object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPServer" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteMcpServerId", + "tags": [ + "McpServers" + ], + "description": "Delete a mcp_server object by its id", + "summary": "Delete mcp_server", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/McpServerIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted mcp_server object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPServer" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsMcpServerId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/mcp_server/{mcp_server_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/McpServerIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/dataset_snapshot": { + "post": { + "tags": [ + "DatasetSnapshots" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "postDatasetSnapshot", + "description": "Create a new dataset_snapshot. If there is an existing dataset_snapshot with the same name as the one specified in the request, will return the existing dataset_snapshot unmodified", + "summary": "Create dataset_snapshot", + "requestBody": { + "description": "Any desired information about the new dataset_snapshot object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateDatasetSnapshot" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new dataset_snapshot object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DatasetSnapshot" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "put": { + "tags": [ + "DatasetSnapshots" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "operationId": "putDatasetSnapshot", + "description": "Create or replace dataset_snapshot. If there is an existing dataset_snapshot with the same name as the one specified in the request, will replace the existing dataset_snapshot with the provided fields", + "summary": "Create or replace dataset_snapshot", + "requestBody": { + "description": "Any desired information about the new dataset_snapshot object", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateDatasetSnapshot" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the new dataset_snapshot object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DatasetSnapshot" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "get": { + "operationId": "getDatasetSnapshot", + "tags": [ + "DatasetSnapshots" + ], + "description": "List out all dataset_snapshots. The dataset_snapshots are sorted by creation date, with the most recently-created dataset_snapshots coming first", + "summary": "List dataset_snapshots", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/AppLimitParam" + }, + { + "$ref": "#/components/parameters/StartingAfter" + }, + { + "$ref": "#/components/parameters/EndingBefore" + }, + { + "$ref": "#/components/parameters/Ids" + }, + { + "$ref": "#/components/parameters/DatasetSnapshotName" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "Returns a list of dataset_snapshot objects", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DatasetSnapshot" + }, + "description": "A list of dataset_snapshot objects" + } + }, + "required": [ + "objects" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsDatasetSnapshot", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/dataset_snapshot`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/dataset_snapshot/{dataset_snapshot_id}": { + "get": { + "operationId": "getDatasetSnapshotId", + "tags": [ + "DatasetSnapshots" + ], + "description": "Get a dataset_snapshot object by its id", + "summary": "Get dataset_snapshot", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetSnapshotIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the dataset_snapshot object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DatasetSnapshot" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "patchDatasetSnapshotId", + "tags": [ + "DatasetSnapshots" + ], + "description": "Partially update a dataset_snapshot object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.", + "summary": "Partially update dataset_snapshot", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetSnapshotIdParam" + } + ], + "requestBody": { + "description": "Fields to update", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchDatasetSnapshot" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the dataset_snapshot object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DatasetSnapshot" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteDatasetSnapshotId", + "tags": [ + "DatasetSnapshots" + ], + "description": "Delete a dataset_snapshot object by its id", + "summary": "Delete dataset_snapshot", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetSnapshotIdParam" + } + ], + "responses": { + "200": { + "description": "Returns the deleted dataset_snapshot object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DatasetSnapshot" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsDatasetSnapshotId", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/dataset_snapshot/{dataset_snapshot_id}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "$ref": "#/components/parameters/DatasetSnapshotIdParam" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/environment": { + "get": { + "operationId": "listEnvironments", + "summary": "List environments", + "description": "List out all environments. The environments are sorted by creation date, with the most recently-created environments first.", + "tags": [ + "Environments" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "schema": { + "anyOf": [ + { + "type": "string", + "format": "uuid" + }, + { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "minItems": 1 + } + ], + "description": "Filter by environment IDs. Supports a single ID or multiple values." + }, + "required": false, + "name": "ids", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "name", + "in": "query" + }, + { + "$ref": "#/components/parameters/OrgName" + } + ], + "responses": { + "200": { + "description": "List of environments", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Environment" + } + } + }, + "required": [ + "objects" + ] + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "post": { + "operationId": "createEnvironment", + "summary": "Create environment", + "description": "Create a new environment", + "tags": [ + "Environments" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateEnvironment" + } + } + } + }, + "responses": { + "200": { + "description": "Created environment", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Environment" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/environment/{environment_id}": { + "get": { + "operationId": "getEnvironment", + "summary": "Get environment", + "tags": [ + "Environments" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "environment_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Environment object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Environment" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "patch": { + "operationId": "updateEnvironment", + "summary": "Partially update environment", + "tags": [ + "Environments" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "environment_id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchEnvironment" + } + } + } + }, + "responses": { + "200": { + "description": "Updated environment", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Environment" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "delete": { + "operationId": "deleteEnvironment", + "summary": "Delete environment", + "tags": [ + "Environments" + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "environment_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Deleted environment", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Environment" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1": { + "get": { + "operationId": "getIndex", + "tags": [ + "Other" + ], + "description": "Default endpoint. Simply replies with 'Hello, World!'. Authorization is not required", + "summary": "Hello world endpoint", + "security": [], + "responses": { + "200": { + "description": "Hello world string", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsIndex", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/insert": { + "post": { + "operationId": "postCrossObjectInsert", + "tags": [ + "CrossObject" + ], + "description": "Insert events and feedback across object types", + "summary": "Cross-object insert", + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "A mapping from event object type -> object id -> events to insert", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CrossObjectInsertRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the inserted row ids for the events on each individual object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CrossObjectInsertResponse" + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "401": { + "description": "No valid API key provided", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "403": { + "description": "The API key doesn’t have permissions to perform the request", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "429": { + "description": "Too many requests hit the API too quickly. We recommend an exponential backoff of your requests", + "headers": { + "Retry-After": { + "schema": { + "type": "string" + } + } + }, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "500": { + "description": "Something went wrong on Braintrust's end. (These are rare.)", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsCrossObjectInsert", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/insert`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/proxy/chat/completions": { + "post": { + "operationId": "proxychatCompletions", + "tags": [ + "Proxy" + ], + "description": "Proxy a chat/completions request to the specified model, converting its format as needed. Will cache if temperature=0 or seed is set.", + "summary": "Proxy chat/completions", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "description": "See the [OpenAI docs](https://platform.openai.com/docs/api-reference/chat/create) for details.", + "required": true, + "content": { + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "responses": { + "200": { + "description": "Proxy response (supports both streaming and non-streaming formats)", + "content": { + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProxyproxychatCompletions", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/proxy/chat/completions`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/proxy/completions": { + "post": { + "operationId": "proxycompletions", + "tags": [ + "Proxy" + ], + "description": "Proxy a completions request to the specified model, converting its format as needed. Will cache if temperature=0 or seed is set.", + "summary": "Proxy completions", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "description": "See the [OpenAI docs](https://platform.openai.com/docs/api-reference/completions/create) for details.", + "required": true, + "content": { + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "responses": { + "200": { + "description": "Proxy response (supports both streaming and non-streaming formats)", + "content": { + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProxyproxycompletions", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/proxy/completions`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/proxy/auto": { + "post": { + "operationId": "proxyauto", + "tags": [ + "Proxy" + ], + "description": "Proxy a request to either chat/completions or completions automatically based on the model. Will cache if temperature=0 or seed is set.", + "summary": "Proxy a model to chat/completions or completions automatically", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "description": "The chat/completions or completions payload (depending on the model)", + "required": true, + "content": { + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "responses": { + "200": { + "description": "Proxy response (supports both streaming and non-streaming formats)", + "content": { + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProxyproxyauto", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/proxy/auto`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/proxy/embeddings": { + "post": { + "operationId": "proxyembeddings", + "tags": [ + "Proxy" + ], + "description": "Proxy an embeddings request to the specified model, converting its format as needed. Will cache automatically.", + "summary": "Proxy embeddings", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "description": "See the [OpenAI docs](https://platform.openai.com/docs/api-reference/embeddings/create) for details.", + "required": true, + "content": { + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "responses": { + "200": { + "description": "Proxy response (supports both streaming and non-streaming formats)", + "content": { + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProxyproxyembeddings", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/proxy/embeddings`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/proxy/credentials": { + "post": { + "operationId": "proxycredentials", + "tags": [ + "Proxy" + ], + "description": "Create a temporary credential which can access the proxy for a limited time. The temporary credential will be allowed to make requests on behalf of the Braintrust API key (or model provider API key) provided in the `Authorization` header. See [docs](/docs/deploy/ai-proxy#create-temporary-credentials) for code examples.", + "summary": "Create temporary credential", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "description": "The temporary credential will be restricted according to the request body.", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "model": { + "type": "string", + "nullable": true, + "description": "Granted model name. Null/undefined to grant usage of all models." + }, + "ttl_seconds": { + "type": "number", + "maximum": 86400, + "default": 600, + "description": "TTL of the temporary credential. 10 minutes by default." + }, + "logging": { + "type": "object", + "nullable": true, + "properties": { + "project_name": { + "type": "string" + }, + "compress_audio": { + "type": "boolean", + "default": true + } + }, + "required": [ + "project_name" + ], + "description": "If present, proxy will log requests to the given Braintrust project name." + } + }, + "description": "Payload for requesting temporary credentials." + } + } + } + }, + "responses": { + "200": { + "description": "Successfully created temporary credential", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string" + } + }, + "required": [ + "key" + ] + } + } + } + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + }, + "options": { + "operationId": "optionsProxyproxycredentials", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/proxy/credentials`)", + "security": [], + "tags": [ + "CORS" + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/proxy/{path+}": { + "post": { + "operationId": "proxy{path+}", + "tags": [ + "Proxy" + ], + "description": "Any requests which do not match the above paths will be proxied directly to the OpenAI API.", + "summary": "Proxy any OpenAI request (fallback)", + "parameters": [ + { + "name": "path+", + "in": "path", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "The path to proxy" + } + ], + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "description": "The request body", + "required": true, + "content": { + "application/json": { + "schema": { + "nullable": true + } + } + } + }, + "responses": { + "200": { + "description": "Proxy response (supports both streaming and non-streaming formats)", + "content": { + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + }, + "options": { + "operationId": "optionsProxyproxy{path+}", + "description": "Enable CORS", + "summary": "Enable CORS (`/v1/proxy/{path+}`)", + "security": [], + "tags": [ + "CORS" + ], + "parameters": [ + { + "name": "path+", + "in": "path", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "The path to proxy" + } + ], + "responses": { + "200": { + "description": "Response for CORS method", + "headers": { + "Access-Control-Allow-Credentials": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Headers": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Methods": { + "schema": { + "type": "string" + } + }, + "Access-Control-Allow-Origin": { + "schema": { + "type": "string" + } + }, + "Access-Control-Max-Age": { + "schema": { + "type": "string" + } + } + }, + "content": {} + }, + "400": { + "description": "The request was unacceptable, often due to missing a required parameter", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "nullable": true + } + } + } + } + } + } + }, + "/v1/eval": { + "post": { + "operationId": "evalLaunch", + "tags": [ + "Evals" + ], + "description": "Launch an evaluation. This is the API-equivalent of the `Eval` function that is built into the Braintrust SDK. In the Eval API, you provide pointers to a dataset, task function, and scoring functions. The API will then run the evaluation, create an experiment, and return the results along with a link to the experiment. To learn more about evals, see the [Evals guide](https://www.braintrust.dev/docs/evaluate).", + "summary": "Launch an eval", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "description": "Eval launch parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RunEval" + } + } + } + }, + "responses": { + "200": { + "description": "Eval launch response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SummarizeExperimentResponse" + } + } + } + } + } + } + } + } +} diff --git a/py/Makefile b/py/Makefile index 86c004f6..87cee9e4 100644 --- a/py/Makefile +++ b/py/Makefile @@ -1,6 +1,6 @@ PYTHON ?= python -.PHONY: lint pylint test test-wheel _template-version clean fixup build verify-build verify help install-build-deps install-dev test-core check-stale-cassettes sync-pytest-pin _check-git-clean bench bench-compare +.PHONY: lint pylint test test-wheel _template-version clean fixup build verify-build verify help install-build-deps install-dev test-core check-stale-cassettes sync-pytest-pin fetch-openapi-spec generate-api-client check-api-client-codegen test-api-codegen _check-git-clean bench bench-compare clean: rm -rf build dist @@ -36,6 +36,18 @@ check-stale-cassettes: sync-pytest-pin: $(PYTHON) scripts/sync-pytest-pin.py +fetch-openapi-spec: + $(PYTHON) scripts/fetch-openapi-spec.py + +generate-api-client: + uv run --no-default-groups --group api-codegen python scripts/generate-api-client.py + +check-api-client-codegen: + uv run --no-default-groups --group api-codegen python scripts/generate-api-client.py --check + +test-api-codegen: + uv run nox -s test_api_codegen + bench: $(PYTHON) -m benchmarks $(BENCH_ARGS) @@ -78,6 +90,10 @@ help: @echo " bench-compare - Compare two benchmark results (BENCH_BASE=... BENCH_NEW=...)" @echo " build - Build Python package" @echo " check-stale-cassettes - Detect orphaned cassette version directories" + @echo " fetch-openapi-spec - Fetch the hash-verified pinned OpenAPI spec" + @echo " generate-api-client - Generate private REST API models from the pinned spec" + @echo " check-api-client-codegen - Check committed REST API models for drift" + @echo " test-api-codegen - Run OpenAPI validator and generator tests" @echo " sync-pytest-pin - Sync [dependency-groups].test pytest pin from matrix" @echo " clean - Remove build artifacts" @echo " help - Show this help message" diff --git a/py/noxfile.py b/py/noxfile.py index d7979a53..6f2cd3ff 100644 --- a/py/noxfile.py +++ b/py/noxfile.py @@ -220,10 +220,11 @@ def _pinned_python_version(): } ERROR_CODES = tuple(range(1, 256)) INTERNAL_TEST_FLAGS = {"--wheel", "--disable-vcr"} -GENERATED_LINT_EXCLUDES = { +GENERATED_LINT_EXCLUDES = ( "src/braintrust/_generated_types.py", "src/braintrust/generated_types.py", -} + "src/braintrust/api/_generated/", +) # --------------------------------------------------------------------------- @@ -755,6 +756,14 @@ def test_core(session): _run_core_tests(session) +@nox.session() +def test_api_codegen(session): + """Test the pinned OpenAPI validator and deterministic model generator.""" + _install_test_deps(session) + _install_group_locked(session, "api-codegen") + session.run("pytest", "-p", "no:braintrust", "tests/api_codegen", *session.posargs) + + @nox.session() def test_braintrust_core(session): # Some tests do specific things if braintrust_core is installed, so run our @@ -823,7 +832,7 @@ def pylint(session): _install_group_locked(session, "test", "lint") result = session.run("git", "ls-files", "**/*.py", silent=True, log=False) - files = [path for path in result.strip().splitlines() if path not in GENERATED_LINT_EXCLUDES] + files = [path for path in result.strip().splitlines() if not path.startswith(GENERATED_LINT_EXCLUDES)] # Also lint repo-root examples/ — they live outside py/ but rely on the # same `lint` dependency-group, so we cover them in the same invocation. examples_result = session.run("git", "-C", "../examples", "ls-files", "**/*.py", silent=True, log=False) @@ -831,9 +840,11 @@ def pylint(session): if not files: return # scripts/ may use APIs only available in the latest pinned Python version - # (e.g. datetime.UTC requires 3.11+); skip them on older versions. + # (e.g. datetime.UTC requires 3.11+); skip them on older versions. tests/api_codegen/ imports + # from scripts/, so it has to go with them -- pylint reports an unresolvable import once + # scripts/ is out of the analyzed set. if _PINNED_PYTHON and sys.version_info[:2] < _PINNED_PYTHON: - files = [f for f in files if not f.startswith("scripts/")] + files = [f for f in files if not f.startswith(("scripts/", "tests/api_codegen/"))] # The lint group skips crewai to avoid vulnerable transitive chromadb # versions, so skip the matching example too. files = [f for f in files if not f.startswith("../examples/crewai/")] diff --git a/py/pyproject.toml b/py/pyproject.toml index 4a4685a4..8e3ab6e2 100644 --- a/py/pyproject.toml +++ b/py/pyproject.toml @@ -287,17 +287,23 @@ lint = [ "llama-index-embeddings-openai", ] -# -- Build deps ---------------------------------------------------------------- +# -- Build and code-generation deps -------------------------------------------- build = [ "setuptools>=82.0.1", ] +api-codegen = [ + "datamodel-code-generator==0.72.4", + "ruff==0.15.21", +] + # -- Dev deps (superset for local development) --------------------------------- dev = [ {include-group = "test"}, {include-group = "build"}, + {include-group = "api-codegen"}, "nox==2026.2.9", "pre-commit==4.6.0", "pylint==4.0.5", diff --git a/py/scripts/fetch-openapi-spec.py b/py/scripts/fetch-openapi-spec.py new file mode 100644 index 00000000..d83e3ba2 --- /dev/null +++ b/py/scripts/fetch-openapi-spec.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""Fetch the exact OpenAPI snapshot pinned in openapi/config.json.""" + +import os +import subprocess +import sys +import tempfile +import urllib.error +import urllib.request +from pathlib import Path + +from openapi_codegen import CONFIG_PATH, SPEC_PATH, CodegenError, load_config, validate_config, verify_spec_hash + + +def _read_source(config): + spec_config = config["spec"] + local_root = os.environ.get("BRAINTRUST_OPENAPI_ROOT") + if local_root: + root = Path(local_root).expanduser().resolve() + source = root / spec_config["path"] + try: + head = subprocess.run( + ["git", "-C", str(root), "rev-parse", "HEAD"], + check=True, + capture_output=True, + text=True, + ).stdout.strip() + except (OSError, subprocess.CalledProcessError) as exc: + raise CodegenError(f"BRAINTRUST_OPENAPI_ROOT is not a readable git checkout: {root}") from exc + if head != spec_config["commit"]: + raise CodegenError( + f"Local braintrust-openapi checkout is at {head}, but config pins {spec_config['commit']}" + ) + try: + return source.read_bytes(), str(source) + except OSError as exc: + raise CodegenError(f"Unable to read local OpenAPI spec {source}: {exc}") from exc + + url = ( + f"https://raw.githubusercontent.com/{spec_config['repository']}/{spec_config['commit']}/{spec_config['path']}" + ) + try: + with urllib.request.urlopen(url, timeout=30) as response: # noqa: S310 - explicitly pinned public source. + return response.read(), url + except (OSError, urllib.error.URLError) as exc: + raise CodegenError(f"Unable to fetch pinned OpenAPI spec from {url}: {exc}") from exc + + +def main(): + config = load_config(CONFIG_PATH) + validate_config(config, check_installed_tools=False) + content, source = _read_source(config) + verify_spec_hash(content, config, source) + SPEC_PATH.parent.mkdir(parents=True, exist_ok=True) + with tempfile.NamedTemporaryFile(dir=SPEC_PATH.parent, delete=False) as temporary: + temporary.write(content) + temporary_path = Path(temporary.name) + # NamedTemporaryFile creates the file 0600 and os.replace preserves that mode, so the committed + # spec would silently lose group/other read access on every fetch. + umask = os.umask(0) + os.umask(umask) + os.chmod(temporary_path, 0o666 & ~umask) + os.replace(temporary_path, SPEC_PATH) + print(f"Fetched {source} -> {SPEC_PATH} ({config['spec']['sha256']})") + + +if __name__ == "__main__": + try: + main() + except CodegenError as exc: + print(f"error: {exc}", file=sys.stderr) + raise SystemExit(1) from exc diff --git a/py/scripts/generate-api-client.py b/py/scripts/generate-api-client.py new file mode 100644 index 00000000..50dfab24 --- /dev/null +++ b/py/scripts/generate-api-client.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""Generate the committed private Braintrust REST API models. + +Usage: + python scripts/generate-api-client.py # regenerate in place + python scripts/generate-api-client.py --check # report drift, leave the worktree alone +""" + +import argparse +import sys +import tempfile +from pathlib import Path + +from openapi_codegen import ( + CONFIG_PATH, + GENERATED_ROOT, + SPEC_PATH, + CodegenError, + atomic_replace_tree, + compare_generated, + generate_tree, + load_config, + read_and_verify_spec, +) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--check", + action="store_true", + help="Regenerate into a temporary directory and diff it against the committed tree.", + ) + args = parser.parse_args() + + config = load_config(CONFIG_PATH) + spec = read_and_verify_spec(config, SPEC_PATH) + with tempfile.TemporaryDirectory(prefix="braintrust-api-codegen-") as temporary: + generated = Path(temporary) / "_generated" + report = generate_tree(generated, config, spec) + if not args.check: + atomic_replace_tree(generated, GENERATED_ROOT) + print(f"Generated {GENERATED_ROOT} from pinned spec: {report}") + return 0 + differences = compare_generated(generated, GENERATED_ROOT) + + if differences: + print("Generated API client drift detected. Run `cd py && make generate-api-client`.", file=sys.stderr) + print("".join(differences), file=sys.stderr) + return 1 + print(f"Generated API client is current: {report}") + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except CodegenError as exc: + print(f"error: {exc}", file=sys.stderr) + raise SystemExit(1) from exc diff --git a/py/scripts/openapi_codegen.py b/py/scripts/openapi_codegen.py new file mode 100644 index 00000000..7c5faea2 --- /dev/null +++ b/py/scripts/openapi_codegen.py @@ -0,0 +1,637 @@ +"""Shared validation and generation helpers for the pinned Braintrust OpenAPI spec.""" + +import copy +import difflib +import hashlib +import importlib.metadata +import json +import os +import re +import shutil +import subprocess +import sys +from pathlib import Path +from typing import Any, Dict, FrozenSet, Iterator, List, Mapping, NamedTuple, Sequence, Set, Tuple + + +REPO_ROOT = Path(__file__).resolve().parents[2] +CONFIG_PATH = REPO_ROOT / "openapi" / "config.json" +SPEC_PATH = REPO_ROOT / "openapi" / "spec.json" +GENERATED_ROOT = REPO_ROOT / "py" / "src" / "braintrust" / "api" / "_generated" +HTTP_METHODS = {"delete", "get", "head", "options", "patch", "post", "put", "trace"} +OPERATION_ID_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$") +SHA_RE = re.compile(r"^[0-9a-f]{40}$") +SHA256_RE = re.compile(r"^[0-9a-f]{64}$") +JSON_SCHEMA_TYPES = {"array", "boolean", "integer", "null", "number", "object", "string"} +# Keywords whose values hold nested schemas. Everything reachable through them has to be walked, +# otherwise an unsupported type hidden under, say, `patternProperties` sails past validation. +_SCHEMA_MAP_KEYWORDS = ("properties", "patternProperties", "dependentSchemas", "definitions", "$defs") +_SCHEMA_CHILD_KEYWORDS = ( + "items", + "additionalProperties", + "unevaluatedProperties", + "unevaluatedItems", + "contains", + "propertyNames", + "not", + "if", + "then", + "else", +) +_SCHEMA_LIST_KEYWORDS = ("allOf", "anyOf", "oneOf", "prefixItems", "items") + + +class CodegenError(RuntimeError): + """An actionable OpenAPI validation or generation failure.""" + + +class ValidationReport(NamedTuple): + operation_count: int + options_operation_count: int + schema_count: int + skip_ids: FrozenSet[str] + + def __str__(self) -> str: + return ( + f"{self.operation_count} supported operations, " + f"{self.options_operation_count} CORS OPTIONS operations removed, " + f"{len(self.skip_ids)} explicitly skipped operations, " + f"{self.schema_count} schemas" + ) + + +def load_config(path: Path = CONFIG_PATH) -> Dict[str, Any]: + try: + config = json.loads(path.read_text(encoding="utf-8")) + except (OSError, json.JSONDecodeError) as exc: + raise CodegenError(f"Unable to read OpenAPI config {path}: {exc}") from exc + if not isinstance(config, dict): + raise CodegenError(f"OpenAPI config {path} must contain a JSON object") + return config + + +def verify_spec_hash(spec_bytes: bytes, config: Mapping[str, Any], source: str) -> None: + expected_hash = _required_string(config, "spec", "sha256") + if not SHA256_RE.fullmatch(expected_hash): + raise CodegenError("openapi/config.json spec.sha256 must be a lowercase 64-character SHA-256") + actual_hash = hashlib.sha256(spec_bytes).hexdigest() + if actual_hash != expected_hash: + raise CodegenError( + f"OpenAPI spec hash mismatch for {source}: expected {expected_hash}, got {actual_hash}. " + "Update the pinned hash intentionally or run make fetch-openapi-spec." + ) + + +def read_and_verify_spec(config: Mapping[str, Any], path: Path = SPEC_PATH) -> Dict[str, Any]: + try: + spec_bytes = path.read_bytes() + except OSError as exc: + raise CodegenError(f"Unable to read pinned OpenAPI spec {path}: {exc}") from exc + verify_spec_hash(spec_bytes, config, str(path)) + try: + spec = json.loads(spec_bytes) + except json.JSONDecodeError as exc: + raise CodegenError(f"Pinned OpenAPI spec {path} is not valid JSON: {exc}") from exc + if not isinstance(spec, dict): + raise CodegenError(f"Pinned OpenAPI spec {path} must contain a JSON object") + return spec + + +def validate_config(config: Mapping[str, Any], check_installed_tools: bool = True) -> None: + if config.get("schema_version") != 1: + raise CodegenError("Unsupported openapi/config.json schema_version; expected 1") + commit = _required_string(config, "spec", "commit") + if not SHA_RE.fullmatch(commit): + raise CodegenError("openapi/config.json spec.commit must be a full lowercase 40-character commit SHA") + _required_string(config, "spec", "repository") + _required_string(config, "spec", "path") + flags = _model_flags(config) + if not flags or not all(isinstance(flag, str) and flag.startswith("--") for flag in flags): + raise CodegenError("model_generator.flags must be a non-empty list of command-line flags") + _endpoint_config(config) + + if check_installed_tools: + for distribution, config_key in (("datamodel-code-generator", "datamodel-code-generator"), ("ruff", "ruff")): + expected = _required_string(config, "tools", config_key) + try: + actual = importlib.metadata.version(distribution) + except importlib.metadata.PackageNotFoundError as exc: + raise CodegenError( + f"Required generator tool {distribution}=={expected} is not installed; " + "run the make target through the api-codegen dependency group" + ) from exc + if actual != expected: + raise CodegenError(f"Generator tool pin mismatch: expected {distribution}=={expected}, got {actual}") + + +def validate_spec(spec: Mapping[str, Any], config: Mapping[str, Any]) -> ValidationReport: + if not isinstance(spec.get("paths"), dict): + raise CodegenError("OpenAPI spec must define a paths object") + components = spec.get("components", {}) + if not isinstance(components, dict) or not isinstance(components.get("schemas", {}), dict): + raise CodegenError("OpenAPI spec components.schemas must be an object") + schemas = components.get("schemas", {}) + + _validate_refs(spec) + operations = list(_iter_operations(spec)) + # Uniqueness is checked before the skip set is resolved: skipped and supported operations share + # one operationId namespace, so a collision between them would otherwise drop the supported + # operation from the normalized spec without any error. + _validate_unique_operation_ids(operations) + endpoint = _endpoint_config(config) + skip_ids = _validate_skip_set(operations, endpoint) + + generated_names: Dict[str, str] = {} + supported_count = 0 + options_count = 0 + for method, path, operation_id, operation, path_item in operations: + if method == "options": + if operation.get("tags") != ["CORS"]: + raise CodegenError( + f"OPTIONS {path} is not tagged only as CORS and cannot be removed during normalization" + ) + options_count += 1 + continue + if operation_id in skip_ids: + continue + if not operation_id or not OPERATION_ID_RE.fullmatch(operation_id): + raise CodegenError(f"Operation {method.upper()} {path} has an invalid operationId: {operation_id!r}") + tags = operation.get("tags") + if not isinstance(tags, list) or len(tags) != 1 or not isinstance(tags[0], str) or not tags[0].strip(): + raise CodegenError(f"Operation {operation_id!r} must have exactly one usable tag") + generated_name = _python_type_name(operation_id) + previous = generated_names.setdefault(generated_name, operation_id) + if previous != operation_id: + raise CodegenError( + f"Inline operation name collision: {previous!r} and {operation_id!r} both generate {generated_name!r}" + ) + _validate_operation_media(operation_id, operation, endpoint, spec) + _validate_path_parameters(operation_id, path, path_item, operation, spec) + supported_count += 1 + + _validate_component_names(schemas) + _validate_json_values_and_types(spec) + return ValidationReport(supported_count, options_count, len(schemas), frozenset(skip_ids)) + + +def normalize_spec(spec: Mapping[str, Any], skip_ids: FrozenSet[str]) -> Dict[str, Any]: + """Remove only CORS OPTIONS and the exact configured skip set.""" + normalized = copy.deepcopy(spec) + for path, path_item in list(normalized["paths"].items()): + for method, operation in list(path_item.items()): + lower_method = method.lower() + if lower_method in HTTP_METHODS and ( + lower_method == "options" or operation.get("operationId") in skip_ids + ): + del path_item[method] + if not any(key.lower() in HTTP_METHODS for key in path_item): + del normalized["paths"][path] + return normalized + + +def generate_tree(output_root: Path, config: Mapping[str, Any], spec: Mapping[str, Any]) -> ValidationReport: + validate_config(config) + report = validate_spec(spec, config) + normalized = normalize_spec(spec, report.skip_ids) + output_root.mkdir(parents=True, exist_ok=True) + normalized_path = output_root.parent / "normalized-spec.json" + normalized_path.write_text( + json.dumps(normalized, sort_keys=True, separators=(",", ":"), ensure_ascii=False) + "\n", encoding="utf-8" + ) + try: + _generate_models(normalized_path, output_root / "models.py", config) + finally: + normalized_path.unlink(missing_ok=True) + _write_generated_file(output_root / "__init__.py", _GENERATED_INIT_BODY, config) + return report + + +def compare_generated(expected_root: Path, actual_root: Path) -> List[str]: + expected_files = _generated_source_files(expected_root) + actual_files = _generated_source_files(actual_root) + differences: List[str] = [] + for relative in sorted(expected_files | actual_files): + expected = expected_root / relative + actual = actual_root / relative + if not expected.exists(): + differences.append(f"Unexpected generated file: {relative}") + continue + if not actual.exists(): + differences.append(f"Missing generated file: {relative}") + continue + if expected.read_bytes() == actual.read_bytes(): + continue + differences.extend( + difflib.unified_diff( + actual.read_text(encoding="utf-8").splitlines(keepends=True), + expected.read_text(encoding="utf-8").splitlines(keepends=True), + fromfile=f"committed/{relative}", + tofile=f"regenerated/{relative}", + ) + ) + return differences + + +def _generated_source_files(root: Path) -> Set[Path]: + """Every committed file in a generated tree, not just ``*.py``. + + Restricting this to ``*.py`` would let a file the generator has stopped emitting survive both + the drift check and the tree replacement, so a stale artifact could sit in the committed tree + while ``check-api-client-codegen`` reported it as current. + """ + return { + path.relative_to(root) + for path in root.rglob("*") + if path.is_file() and "__pycache__" not in path.parts and not path.name.startswith(".") + } + + +def atomic_replace_tree(source_root: Path, destination_root: Path) -> None: + destination_root.mkdir(parents=True, exist_ok=True) + source_files = _generated_source_files(source_root) + destination_files = _generated_source_files(destination_root) + for relative in destination_files - source_files: + (destination_root / relative).unlink() + for relative in source_files: + source = source_root / relative + destination = destination_root / relative + destination.parent.mkdir(parents=True, exist_ok=True) + temporary = destination.with_name(f".{destination.name}.tmp") + temporary.write_bytes(source.read_bytes()) + os.replace(temporary, destination) + _prune_empty_directories(destination_root) + + +def _prune_empty_directories(root: Path) -> None: + """Drop directories the generator no longer populates, deepest first. + + A directory left behind after its last module is removed still imports as a namespace package, + so emptied packages have to go with their files. + """ + directories = sorted((path for path in root.rglob("*") if path.is_dir()), key=lambda p: len(p.parts), reverse=True) + for directory in directories: + if directory.name == "__pycache__": + continue + if any(child.name != "__pycache__" for child in directory.iterdir()): + continue + shutil.rmtree(directory) + + +def _generate_models(spec_path: Path, output_path: Path, config: Mapping[str, Any]) -> None: + placeholder = "CONTENT_HASH_PLACEHOLDER" + header = _generated_header(config, placeholder).rstrip() + command = [ + sys.executable, + "-m", + "datamodel_code_generator", + "--input", + str(spec_path), + "--output", + str(output_path), + *_model_flags(config), + "--custom-file-header", + header, + ] + try: + subprocess.run(command, check=True, capture_output=True, text=True) + except subprocess.CalledProcessError as exc: + detail = exc.stderr.strip() or exc.stdout.strip() or str(exc) + raise CodegenError(f"datamodel-code-generator failed: {detail}") from exc + # datamodel-code-generator's own `--formatters=ruff-format` pass is not a fixed point; running + # the pinned ruff again is what makes the committed output stable. + subprocess.run( + [sys.executable, "-m", "ruff", "format", str(output_path)], check=True, capture_output=True, text=True + ) + generated = output_path.read_text(encoding="utf-8") + marker = f"# Content SHA-256: {placeholder}" + if marker not in generated: + raise CodegenError("Generated models did not contain the expected content hash marker") + body = generated.split(marker, 1)[1].lstrip("\n") + content_hash = hashlib.sha256(body.encode()).hexdigest() + # Substituting the hash only rewrites characters inside a comment, so the file stays formatted. + _write_checked(output_path, generated.replace(placeholder, content_hash, 1)) + + +def _write_generated_file(path: Path, body: str, config: Mapping[str, Any]) -> None: + content_hash = hashlib.sha256(body.encode()).hexdigest() + _write_checked(path, _generated_header(config, content_hash) + "\n\n" + body) + + +def _write_checked(path: Path, text: str) -> None: + compile(text, str(path), "exec") + path.write_text(text, encoding="utf-8") + + +def _generated_header(config: Mapping[str, Any], content_hash: str) -> str: + return "\n".join( + [ + "# Generated by scripts/generate-api-client.py. DO NOT EDIT.", + f"# OpenAPI commit: {_required_string(config, 'spec', 'commit')}", + f"# OpenAPI spec SHA-256: {_required_string(config, 'spec', 'sha256')}", + f"# datamodel-code-generator: {_required_string(config, 'tools', 'datamodel-code-generator')}", + f"# ruff: {_required_string(config, 'tools', 'ruff')}", + f"# Generator Python: {_required_string(config, 'tools', 'python')}", + f"# Content SHA-256: {content_hash}", + ] + ) + + +_GENERATED_INIT_BODY = '''"""Private generated REST API implementation. + +Import submodules explicitly (``from braintrust.api._generated import models``); importing this +package pulls in no models. +""" +''' + + +def _iter_operations( + spec: Mapping[str, Any], +) -> Iterator[Tuple[str, str, Any, Mapping[str, Any], Mapping[str, Any]]]: + for path, path_item in spec.get("paths", {}).items(): + if not isinstance(path_item, dict): + raise CodegenError(f"Path item {path!r} must be an object") + for method, operation in path_item.items(): + lower_method = method.lower() + if lower_method not in HTTP_METHODS: + continue + if not isinstance(operation, dict): + raise CodegenError(f"Operation {method.upper()} {path} must be an object") + yield lower_method, path, operation.get("operationId"), operation, path_item + + +def _endpoint_config(config: Mapping[str, Any]) -> Mapping[str, Any]: + endpoint = config.get("endpoint_generator") + if not isinstance(endpoint, dict) or endpoint.get("schema_version") != 1: + raise CodegenError("Unsupported endpoint_generator schema_version; expected 1") + if not isinstance(endpoint.get("skip_tags"), dict): + raise CodegenError("endpoint_generator.skip_tags must be an object") + for key in ("supported_request_media_types", "supported_response_media_types", "supported_success_statuses"): + values = endpoint.get(key) + if not isinstance(values, list) or not values or not all(isinstance(value, str) for value in values): + raise CodegenError(f"Config key endpoint_generator.{key} must be a non-empty list of strings") + return endpoint + + +def _validate_unique_operation_ids( + operations: Sequence[Tuple[str, str, Any, Mapping[str, Any], Mapping[str, Any]]], +) -> None: + seen: Dict[str, str] = {} + for method, path, operation_id, _, _ in operations: + if method == "options" or operation_id is None: + continue + location = f"{method.upper()} {path}" + previous = seen.setdefault(operation_id, location) + if previous != location: + raise CodegenError(f"Duplicate operationId {operation_id!r} on {previous} and {location}") + + +def _validate_skip_set( + operations: Sequence[Tuple[str, str, Any, Mapping[str, Any], Mapping[str, Any]]], endpoint: Mapping[str, Any] +) -> Set[str]: + skip_tags = endpoint["skip_tags"] + configured_ids: Set[str] = set() + operation_tags: Dict[str, Set[str]] = {} + for method, path, operation_id, operation, _ in operations: + if method == "options": + continue + if operation_id is not None: + operation_tags[operation_id] = set(operation.get("tags", [])) + for tag, skip_config in skip_tags.items(): + if not isinstance(tag, str) or not isinstance(skip_config, dict): + raise CodegenError("Each endpoint_generator.skip_tags entry must be an object keyed by a tag") + reason = skip_config.get("reason") + ids = skip_config.get("operation_ids") + if ( + not isinstance(reason, str) + or not reason.strip() + or not isinstance(ids, list) + or not all(isinstance(value, str) for value in ids) + ): + raise CodegenError(f"Skip tag {tag!r} must have a reason and an operation_ids list") + if len(ids) != len(set(ids)): + raise CodegenError(f"Skip tag {tag!r} contains duplicate operation IDs") + actual_ids = {operation_id for operation_id, tags in operation_tags.items() if tag in tags} + expected_ids = set(ids) + if actual_ids != expected_ids: + missing = sorted(actual_ids - expected_ids) + stale = sorted(expected_ids - actual_ids) + raise CodegenError( + f"Skip tag {tag!r} does not match the spec exactly; unlisted={missing}, stale={stale}. " + "Update the explicit skip set and review each operation." + ) + overlap = configured_ids & expected_ids + if overlap: + raise CodegenError(f"Operations occur in more than one skip tag: {', '.join(sorted(overlap))}") + configured_ids.update(expected_ids) + return configured_ids + + +def _validate_refs(spec: Mapping[str, Any]) -> None: + for value in _walk_values(spec): + if not isinstance(value, dict) or "$ref" not in value: + continue + reference = value["$ref"] + if not isinstance(reference, str) or not reference.startswith("#/"): + raise CodegenError(f"Only local OpenAPI references are supported, got {reference!r}") + _resolve_ref(reference, spec) + + +def _resolve_ref(reference: str, spec: Mapping[str, Any]) -> Any: + current: Any = spec + for raw_part in reference[2:].split("/"): + part = raw_part.replace("~1", "/").replace("~0", "~") + if not isinstance(current, dict) or part not in current: + raise CodegenError(f"Unresolved OpenAPI reference {reference!r}") + current = current[part] + return current + + +def _resolve_object(value: Mapping[str, Any], spec: Mapping[str, Any]) -> Mapping[str, Any]: + seen: Set[str] = set() + while "$ref" in value: + reference = value["$ref"] + if reference in seen: + raise CodegenError(f"Cyclic direct OpenAPI reference {reference!r}") + seen.add(reference) + resolved = _resolve_ref(reference, spec) + if not isinstance(resolved, dict): + raise CodegenError(f"OpenAPI reference {reference!r} must resolve to an object") + value = resolved + return value + + +def _validate_operation_media( + operation_id: str, operation: Mapping[str, Any], endpoint: Mapping[str, Any], spec: Mapping[str, Any] +) -> None: + request_body = operation.get("requestBody") + if request_body is not None: + if not isinstance(request_body, dict): + raise CodegenError(f"Operation {operation_id!r} has an invalid request body") + request_body = _resolve_object(request_body, spec) + content = request_body.get("content", {}) + if not isinstance(content, dict) or not content: + raise CodegenError(f"Operation {operation_id!r} request body must define content") + unsupported = set(content) - set(endpoint["supported_request_media_types"]) + if unsupported: + raise CodegenError( + f"Operation {operation_id!r} has unsupported request media type(s): {sorted(unsupported)}" + ) + + responses = operation.get("responses") + if not isinstance(responses, dict): + raise CodegenError(f"Operation {operation_id!r} must define responses") + success_count = 0 + for status, response in responses.items(): + status_string = str(status) + if not status_string.startswith("2"): + continue + success_count += 1 + if status_string not in endpoint["supported_success_statuses"]: + raise CodegenError(f"Operation {operation_id!r} has unsupported success status {status_string}") + if not isinstance(response, dict): + raise CodegenError(f"Operation {operation_id!r} response {status_string} must be an object") + response = _resolve_object(response, spec) + content = response.get("content", {}) + if status_string == "204" and not content: + continue + if not isinstance(content, dict) or not content: + raise CodegenError(f"Operation {operation_id!r} response {status_string} must define content") + unsupported = set(content) - set(endpoint["supported_response_media_types"]) + if unsupported: + raise CodegenError( + f"Operation {operation_id!r} has unsupported success response media type(s): {sorted(unsupported)}" + ) + for media_type, media in content.items(): + if not isinstance(media, dict): + raise CodegenError( + f"Operation {operation_id!r} response {status_string} media type {media_type!r} must be an object" + ) + if media_type == "text/plain": + schema = _resolve_object(media.get("schema", {}), spec) + if schema.get("type") != "string": + raise CodegenError(f"Operation {operation_id!r} text/plain success response must be a string") + if not success_count: + raise CodegenError(f"Operation {operation_id!r} has no supported success response") + + +def _validate_path_parameters( + operation_id: str, + path: str, + path_item: Mapping[str, Any], + operation: Mapping[str, Any], + spec: Mapping[str, Any], +) -> None: + template_names = set(re.findall(r"\{([^{}]+)\}", path)) + path_parameters: Dict[str, Mapping[str, Any]] = {} + for parameter in [*path_item.get("parameters", []), *operation.get("parameters", [])]: + if not isinstance(parameter, dict): + raise CodegenError(f"Operation {operation_id!r} has an invalid parameter") + parameter = _resolve_object(parameter, spec) + if parameter.get("in") == "path": + name = parameter.get("name") + if not isinstance(name, str): + raise CodegenError(f"Operation {operation_id!r} has a path parameter without a name") + path_parameters[name] = parameter + if template_names != set(path_parameters): + raise CodegenError( + f"Operation {operation_id!r} path template/parameter mismatch: " + f"template={sorted(template_names)}, declared={sorted(path_parameters)}" + ) + for name, parameter in path_parameters.items(): + if parameter.get("required") is not True: + raise CodegenError(f"Operation {operation_id!r} path parameter {name!r} must be required") + schema = parameter.get("schema") + if not isinstance(schema, dict): + raise CodegenError(f"Operation {operation_id!r} path parameter {name!r} must define a schema") + schema = _resolve_object(schema, spec) + if schema.get("type") not in {"boolean", "integer", "number", "string"}: + raise CodegenError(f"Operation {operation_id!r} path parameter {name!r} must be scalar") + + +def _validate_component_names(schemas: Mapping[str, Any]) -> None: + names: Dict[str, str] = {} + for schema_name in schemas: + generated_name = _python_type_name(schema_name) + previous = names.setdefault(generated_name, schema_name) + if previous != schema_name: + raise CodegenError( + f"Schema name collision: {previous!r} and {schema_name!r} both generate {generated_name!r}" + ) + + +def _validate_json_values_and_types(spec: Mapping[str, Any]) -> None: + """Validate every schema in the spec: the named components plus every inline ``schema`` value.""" + schema_roots: List[Mapping[str, Any]] = list(spec.get("components", {}).get("schemas", {}).values()) + schema_roots.extend( + value["schema"] + for value in _walk_values(spec) + if isinstance(value, dict) and isinstance(value.get("schema"), dict) + ) + for schema_root in schema_roots: + _validate_schema_values(schema_root) + + +def _validate_schema_values(schema: Mapping[str, Any]) -> None: + schema_type = schema.get("type") + if schema_type is not None and schema_type not in JSON_SCHEMA_TYPES: + raise CodegenError(f"Unsupported non-JSON schema type {schema_type!r}") + for key in ("default", "enum", "example"): + if key in schema: + try: + json.dumps(schema[key], allow_nan=False) + except (TypeError, ValueError) as exc: + raise CodegenError(f"Schema {key} value is not JSON-compatible: {schema[key]!r}") from exc + + children: List[Any] = [] + for key in _SCHEMA_MAP_KEYWORDS: + mapping = schema.get(key) + if isinstance(mapping, dict): + children.extend(mapping.values()) + for key in _SCHEMA_CHILD_KEYWORDS: + child = schema.get(key) + if isinstance(child, dict): + children.append(child) + # `items` is a single schema in 3.0 and may be a tuple of schemas in 3.1, so it appears in both + # the single-child and the list keyword sets. + for key in _SCHEMA_LIST_KEYWORDS: + child_list = schema.get(key) + if isinstance(child_list, list): + children.extend(child_list) + for child in children: + if isinstance(child, dict): + _validate_schema_values(child) + + +def _walk_values(value: Any) -> Iterator[Any]: + yield value + if isinstance(value, dict): + for child in value.values(): + yield from _walk_values(child) + elif isinstance(value, list): + for child in value: + yield from _walk_values(child) + + +def _python_type_name(value: str) -> str: + words = [word for word in re.split(r"[^A-Za-z0-9]+", value) if word] + if not words: + return "Model" + return "".join(word[:1].upper() + word[1:] for word in words) + + +def _model_flags(config: Mapping[str, Any]) -> Sequence[str]: + flags = config.get("model_generator", {}).get("flags") + if not isinstance(flags, list): + raise CodegenError("Missing required config key model_generator.flags") + return flags + + +def _required_string(config: Mapping[str, Any], *path: str) -> str: + value: Any = config + for key in path: + if not isinstance(value, dict) or key not in value: + raise CodegenError(f"Missing required config key {'.'.join(path)}") + value = value[key] + if not isinstance(value, str) or not value: + raise CodegenError(f"Config key {'.'.join(path)} must be a non-empty string") + return value diff --git a/py/src/braintrust/api/_generated/__init__.py b/py/src/braintrust/api/_generated/__init__.py new file mode 100644 index 00000000..e6768440 --- /dev/null +++ b/py/src/braintrust/api/_generated/__init__.py @@ -0,0 +1,13 @@ +# Generated by scripts/generate-api-client.py. DO NOT EDIT. +# OpenAPI commit: 9daf27f19d9e0340304d7a3e7d0edb28380b94c6 +# OpenAPI spec SHA-256: 5ec753c0263c0c44cd04f741edfc7e8bad491cc25a2113d029e84edc076520f0 +# datamodel-code-generator: 0.72.4 +# ruff: 0.15.21 +# Generator Python: 3.14 +# Content SHA-256: 730aa723c7c8b52ae9d2647c910a95e3402ed18b65dbb744255877b93c3fd421 + +"""Private generated REST API implementation. + +Import submodules explicitly (``from braintrust.api._generated import models``); importing this +package pulls in no models. +""" diff --git a/py/src/braintrust/api/_generated/models.py b/py/src/braintrust/api/_generated/models.py new file mode 100644 index 00000000..305a2f16 --- /dev/null +++ b/py/src/braintrust/api/_generated/models.py @@ -0,0 +1,6729 @@ +# Generated by scripts/generate-api-client.py. DO NOT EDIT. +# OpenAPI commit: 9daf27f19d9e0340304d7a3e7d0edb28380b94c6 +# OpenAPI spec SHA-256: 5ec753c0263c0c44cd04f741edfc7e8bad491cc25a2113d029e84edc076520f0 +# datamodel-code-generator: 0.72.4 +# ruff: 0.15.21 +# Generator Python: 3.14 +# Content SHA-256: 8624c6f9c7bfc2e7c8f70127fd25e25269976b285526b0dc5af8223bbbdc4eb7 + +from typing_extensions import NotRequired +from typing import Any, Literal, TypeAlias, TypedDict +from collections.abc import Mapping, Sequence + + +class AISecret(TypedDict): + created: NotRequired[str | None] + """ + Date of AI secret creation + """ + id: str + """ + Unique identifier for the AI secret + """ + metadata: NotRequired[Mapping[str, Any] | None] + name: str + """ + Name of the AI secret + """ + org_id: str + """ + Unique identifier for the organization + """ + preview_secret: NotRequired[str | None] + secret_updated_at: NotRequired[str | None] + """ + Date of last update to the encrypted secret value itself + """ + secret_updated_by_user_id: NotRequired[str | None] + """ + User id of the last update to the encrypted secret value + """ + type: NotRequired[str | None] + updated_at: NotRequired[str | None] + """ + Date of last AI secret update + """ + + +AISecretType: TypeAlias = str | Sequence[str] + + +AclIdParam: TypeAlias = str +""" +Acl id +""" + + +AclListGroupId: TypeAlias = str +""" +Id of the group the ACL applies to. Exactly one of `user_id` and `group_id` will be provided +""" + + +AclListOrgObjectId: TypeAlias = str +""" +The id of the object the ACL applies to +""" + + +AclListOrgObjectType: TypeAlias = Literal[ + "organization", + "project", + "experiment", + "dataset", + "prompt", + "prompt_session", + "group", + "role", + "org_member", + "project_log", + "org_project", + "org_audit_logs", +] +""" +The object type that the ACL applies to +""" + + +AclListPermission: TypeAlias = Literal[ + "create", + "read", + "update", + "delete", + "create_acls", + "read_acls", + "update_acls", + "delete_acls", +] +""" +Each permission permits a certain type of operation on an object in the system + +Permissions can be assigned to to objects on an individual basis, or grouped into roles +""" + + +AclListRestrictObjectType: TypeAlias = Literal[ + "organization", + "project", + "experiment", + "dataset", + "prompt", + "prompt_session", + "group", + "role", + "org_member", + "project_log", + "org_project", + "org_audit_logs", +] +""" +The object type that the ACL applies to +""" + + +AclListRoleId: TypeAlias = str +""" +Id of the role the ACL grants. Exactly one of `permission` and `role_id` will be provided +""" + + +AclListUserId: TypeAlias = str +""" +Id of the user the ACL applies to. Exactly one of `user_id` and `group_id` will be provided +""" + + +AclObjectId: TypeAlias = str +""" +The id of the object the ACL applies to +""" + + +AclObjectType: TypeAlias = Literal[ + "organization", + "project", + "experiment", + "dataset", + "prompt", + "prompt_session", + "group", + "role", + "org_member", + "project_log", + "org_project", + "org_audit_logs", +] +""" +The object type that the ACL applies to +""" + + +class Agent(TypedDict): + created: NotRequired[str | None] + """ + Date of agent creation + """ + description: NotRequired[str | None] + """ + Textual description of the agent + """ + id: str + """ + Unique identifier for the agent + """ + kind: str + """ + Agent classification: 'custom' for customer-defined agents, 'loop' for built-in Loop agents. + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + User-controlled metadata about the agent + """ + name: str + """ + Name of the agent. Within a project, agent names are unique + """ + project_id: str + """ + Unique identifier for the project that the agent belongs under + """ + slug: str + """ + Stable, URL-safe identifier for the agent, unique within its project. + """ + user_id: str + + +AgentIdParam: TypeAlias = str +""" +Agent id +""" + + +AgentName: TypeAlias = str +""" +Name of the agent to search for +""" + + +AiSecretIdParam: TypeAlias = str +""" +AiSecret id +""" + + +AiSecretName: TypeAlias = str +""" +Name of the ai_secret to search for +""" + + +class ApiKey(TypedDict): + created: NotRequired[str | None] + """ + Date of api key creation + """ + id: str + """ + Unique identifier for the api key + """ + name: str + """ + Name of the api key + """ + org_id: NotRequired[str | None] + """ + Unique identifier for the organization + """ + preview_name: str + user_email: NotRequired[str | None] + """ + The user's email + """ + user_family_name: NotRequired[str | None] + """ + Family name of the user + """ + user_given_name: NotRequired[str | None] + """ + Given name of the user + """ + user_id: NotRequired[str | None] + """ + Unique identifier for the user + """ + + +ApiKeyIdParam: TypeAlias = str +""" +ApiKey id +""" + + +ApiKeyName: TypeAlias = str +""" +Name of the api_key to search for +""" + + +AppLimitParam: TypeAlias = int | None +""" +Limit the number of objects to return +""" + + +AppLimitWithDefaultParam: TypeAlias = int | None +""" +Limit the number of objects to return +""" + + +AutomationStatus: TypeAlias = Literal["active", "paused"] +""" +Whether the automation is active or paused. +""" + + +class BatchedFacetDataFacet(TypedDict): + embedding_model: NotRequired[str] + """ + The embedding model to use for vectorizing facet results. + """ + model: NotRequired[str] + """ + The model to use for facet extraction + """ + name: str + """ + The name of the facet + """ + no_match_pattern: NotRequired[str] + """ + Regex pattern to identify outputs that do not match the facet. If the output matches, the facet will be saved as 'no_match' + """ + prompt: str + """ + The prompt to use for LLM extraction. The preprocessed text will be provided as context. + """ + + +class PreprocessorPreprocessor(TypedDict): + id: str + type: Literal["function"] + version: NotRequired[str] + """ + The version of the function + """ + + +class PreprocessorPreprocessor2(TypedDict): + pass + + +class PreprocessorPreprocessor3(PreprocessorPreprocessor, PreprocessorPreprocessor2): + pass + + +class ChatCompletionContentPartFileFile(TypedDict): + file_data: NotRequired[str] + file_id: NotRequired[str] + filename: NotRequired[str] + + +class ChatCompletionContentPartFileWithTitle(TypedDict): + file: ChatCompletionContentPartFileFile + type: Literal["file"] + + +class ChatCompletionContentPartImageWithTitleImageUrl(TypedDict): + detail: NotRequired[Literal["auto"] | Literal["low"] | Literal["high"]] + url: str + + +class ChatCompletionContentPartImageWithTitle(TypedDict): + image_url: ChatCompletionContentPartImageWithTitleImageUrl + type: Literal["image_url"] + + +class ChatCompletionContentPartTextCacheControl(TypedDict): + type: Literal["ephemeral"] + + +class ChatCompletionContentPartText(TypedDict): + cache_control: NotRequired[ChatCompletionContentPartTextCacheControl] + text: NotRequired[str] + type: Literal["text"] + + +class ChatCompletionContentPartTextWithTitleCacheControl(TypedDict): + type: Literal["ephemeral"] + + +class ChatCompletionContentPartTextWithTitle(TypedDict): + cache_control: NotRequired[ChatCompletionContentPartTextWithTitleCacheControl] + text: NotRequired[str] + type: Literal["text"] + + +class ChatCompletionMessageParamChatCompletionMessageParam(TypedDict): + content: NotRequired[str | Sequence[ChatCompletionContentPartText]] + name: NotRequired[str] + role: Literal["system"] + + +class ChatCompletionMessageParamChatCompletionMessageParam2FunctionCall(TypedDict): + arguments: str + name: str + + +class ChatCompletionMessageParamChatCompletionMessageParam3(TypedDict): + content: NotRequired[str | Sequence[ChatCompletionContentPartText]] + role: Literal["tool"] + tool_call_id: NotRequired[str] + + +class ChatCompletionMessageParamChatCompletionMessageParam4(TypedDict): + content: str | None + name: str + role: Literal["function"] + + +class ChatCompletionMessageParamChatCompletionMessageParam5(TypedDict): + content: NotRequired[str | Sequence[ChatCompletionContentPartText]] + name: NotRequired[str] + role: Literal["developer"] + + +class ChatCompletionMessageParamChatCompletionMessageParam6(TypedDict): + content: NotRequired[str | None] + role: Literal["model"] + + +class ChatCompletionMessageReasoning(TypedDict): + content: NotRequired[str | None] + id: NotRequired[str | None] + + +class ChatCompletionMessageToolCallFunction(TypedDict): + arguments: str + name: str + + +class ChatCompletionMessageToolCall(TypedDict): + function: ChatCompletionMessageToolCallFunction + id: str + type: Literal["function"] + + +class CodeBundleLocationPosition(TypedDict): + type: Literal["task"] + + +class CodeBundleLocationPosition1(TypedDict): + index: int + type: Literal["scorer"] + + +class CodeBundleLocationPosition2(TypedDict): + index: int + type: Literal["classifier"] + + +class CodeBundleLocation(TypedDict): + eval_name: str + position: CodeBundleLocationPosition | CodeBundleLocationPosition1 | CodeBundleLocationPosition2 + type: Literal["experiment"] + + +class CodeBundleLocation1(TypedDict): + index: int + type: Literal["function"] + + +class CodeBundleLocation2SandboxSpec(TypedDict): + provider: Literal["modal"] + snapshot_ref: str + """ + sandbox snapshot ref + """ + + +class CodeBundleLocation2SandboxSpec1(TypedDict): + provider: Literal["lambda"] + + +class CodeBundleLocation2(TypedDict): + entrypoints: NotRequired[Sequence[str]] + """ + Which entrypoints to execute in the sandbox + """ + eval_name: str + evaluator_definition: NotRequired[Any | None] + """ + Definition of current evaluator with parameters + """ + parameters: NotRequired[Mapping[str, Any]] + """ + Parameter values for sandbox eval execution + """ + sandbox_spec: CodeBundleLocation2SandboxSpec | CodeBundleLocation2SandboxSpec1 + type: Literal["sandbox"] + + +class CodeBundleRuntimeContext(TypedDict): + runtime: Literal["node", "python", "browser", "quickjs"] + version: str + + +class CodeBundle(TypedDict): + bundle_id: NotRequired[str | None] + location: CodeBundleLocation | CodeBundleLocation1 | CodeBundleLocation2 + preview: NotRequired[str | None] + """ + A preview of the code + """ + runtime_context: CodeBundleRuntimeContext + + +ComparisonExperimentId: TypeAlias = str +""" +The experiment to compare against, if summarizing scores and metrics. If omitted, will fall back to the `base_exp_id` stored in the experiment metadata, and then to the most recent experiment run in the same project. Must pass `summarize_scores=true` for this id to be used +""" + + +class CreateAISecret(TypedDict): + metadata: NotRequired[Mapping[str, Any] | None] + name: str + """ + Name of the AI secret + """ + org_name: NotRequired[str | None] + """ + For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the AI Secret belongs in. + """ + secret: NotRequired[str | None] + """ + Secret value. If omitted in a PUT request, the existing secret value will be left intact, not replaced with null. + """ + type: NotRequired[str | None] + + +class CreateAgent(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the agent + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + User-controlled metadata about the agent + """ + name: str + """ + Name of the agent. Within a project, agent names are unique + """ + project_id: str + """ + Unique identifier for the project that the agent belongs under + """ + + +class CreateDataset(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the dataset + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + User-controlled metadata about the dataset + """ + name: str + """ + Name of the dataset. Within a project, dataset names are unique + """ + project_id: str + """ + Unique identifier for the project that the dataset belongs under + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the dataset + """ + + +class CreateDatasetSnapshot(TypedDict): + dataset_id: str + """ + Unique identifier for the dataset that this snapshot belongs to + """ + description: NotRequired[str | None] + """ + Textual description of the dataset snapshot + """ + name: str + """ + Name of the dataset snapshot + """ + xact_id: str + """ + Transaction id of the brainstore version at the time of the snapshot + """ + + +class CreateEnvironment(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the environment + """ + name: str + """ + Name of the environment + """ + org_name: NotRequired[str | None] + """ + For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the environment belongs in. + """ + slug: str + """ + A url-friendly, unique identifier for the environment within an organization + """ + + +class CreateExperimentInternalMetadata(TypedDict): + dataset_filter: NotRequired[Mapping[str, Any] | None] + """ + BTQL filter payload used to evaluate a subset of a linked dataset. + """ + + +class CreateFunctionFunctionSchema(TypedDict): + parameters: NotRequired[Any | None] + returns: NotRequired[Any | None] + + +class CreateFunctionOrigin(TypedDict): + internal: NotRequired[bool | None] + """ + The function exists for internal purposes and should not be displayed in the list of functions. + """ + object_id: str + """ + Id of the object the function is originating from + """ + object_type: AclObjectType + + +class CreateGroup(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the group + """ + member_groups: NotRequired[Sequence[str] | None] + """ + Ids of the groups this group inherits from + + An inheriting group has all the users contained in its member groups, as well as all of their inherited users + """ + member_users: NotRequired[Sequence[str] | None] + """ + Ids of users which belong to this group + """ + name: str + """ + Name of the group + """ + org_name: NotRequired[str | None] + """ + For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the group belongs in. + """ + + +class CreateMCPServer(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the MCP server + """ + name: str + """ + Name of the MCP server. Within a project, MCP server names are unique + """ + project_id: str + """ + Unique identifier for the project that the MCP server belongs under + """ + url: str + """ + URL of the MCP server endpoint + """ + + +class CreateProject(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the project + """ + name: str + """ + Name of the project + """ + org_name: NotRequired[str | None] + """ + For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the project belongs in. + """ + + +class CreateProjectAutomationConfigAction(TypedDict): + type: Literal["webhook"] + """ + The type of action to take + """ + url: str + """ + The webhook URL to send the request to + """ + + +class CreateProjectAutomationConfigAction1(TypedDict): + channel: str + """ + The Slack channel ID to post to + """ + message_template: NotRequired[str] + """ + Custom message template for the alert + """ + type: Literal["slack"] + """ + The type of action to take + """ + workspace_id: str + """ + The Slack workspace ID to post to + """ + + +class CreateProjectAutomationConfig(TypedDict): + action: CreateProjectAutomationConfigAction | CreateProjectAutomationConfigAction1 + """ + The action to take when the automation rule is triggered + """ + btql_filter: str + """ + BTQL filter to identify rows for the automation rule + """ + event_type: Literal["logs"] + """ + The type of automation. + """ + interval_seconds: float + """ + Perform the triggered action at most once in this interval of seconds + """ + + +class CreateProjectAutomationConfig1Credentials(TypedDict): + external_id: str + """ + The automation-specific external id component (auto-generated by default) + """ + role_arn: str + """ + The ARN of the IAM role to use + """ + type: Literal["aws_iam"] + + +class CreateProjectAutomationConfig1Credentials1(TypedDict): + service_account_email: str + """ + The GCP service account email to impersonate + """ + type: Literal["gcp_service_account"] + + +class CreateProjectAutomationConfig1ExportDefinition(TypedDict): + type: Literal["log_traces"] + + +class CreateProjectAutomationConfig1ExportDefinition1(TypedDict): + type: Literal["log_spans"] + + +class CreateProjectAutomationConfig1ExportDefinition2(TypedDict): + btql_query: str + """ + The BTQL query to export + """ + type: Literal["btql_query"] + + +class CreateProjectAutomationConfig2(TypedDict): + batch_size: NotRequired[int | None] + """ + The maximum number of result rows to write per async query batch + """ + created_by_user_id: str + """ + The user who submitted the async query + """ + event_type: Literal["async_query"] + """ + The type of automation. + """ + format: Literal["jsonl"] + """ + The materialized result format + """ + object_id: str + """ + The source object ID for the async query + """ + object_type: Literal["project_logs", "experiment", "dataset", "playground_logs"] + """ + The source object type for the async query + """ + query: str + """ + The SQL query to execute asynchronously + """ + status: NotRequired[AutomationStatus] + + +class CreateProjectAutomationConfig4Action(TypedDict): + type: Literal["webhook"] + """ + The type of action to take + """ + url: str + """ + The webhook URL to send the request to + """ + + +class CreateProjectAutomationConfig4Action1(TypedDict): + channel: str + """ + The Slack channel ID to post to + """ + message_template: NotRequired[str] + """ + Custom message template for the alert + """ + type: Literal["slack"] + """ + The type of action to take + """ + workspace_id: str + """ + The Slack workspace ID to post to + """ + + +class CreateProjectAutomationConfig4(TypedDict): + action: CreateProjectAutomationConfig4Action | CreateProjectAutomationConfig4Action1 + """ + The action to take when the automation rule is triggered + """ + environment_filter: NotRequired[Sequence[str]] + """ + Optional list of environment slugs to filter by + """ + event_type: Literal["environment_update"] + """ + The type of automation. + """ + + +class CreateProjectTag(TypedDict): + color: NotRequired[str | None] + """ + Color of the tag for the UI + """ + description: NotRequired[str | None] + """ + Textual description of the project tag + """ + name: str + """ + Name of the project tag + """ + project_id: str + """ + Unique identifier for the project that the project tag belongs under + """ + + +class CreateServiceTokenOutput(TypedDict): + created: NotRequired[str | None] + """ + Date of service token creation + """ + id: str + """ + Unique identifier for the service token + """ + key: str + """ + The raw service token. It will only be exposed this one time + """ + name: str + """ + Name of the service token + """ + org_id: NotRequired[str | None] + """ + Unique identifier for the organization + """ + preview_name: str + service_account_email: NotRequired[str | None] + """ + The service account email (not routable) + """ + service_account_id: NotRequired[str | None] + """ + Unique identifier for the service token + """ + service_account_name: NotRequired[str | None] + """ + The service account name + """ + + +class CreateSpanIFrame(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the span iframe + """ + name: str + """ + Name of the span iframe + """ + post_message: NotRequired[bool | None] + """ + Whether to post messages to the iframe containing the span's data. This is useful when you want to render more data than fits in the URL. + """ + project_id: str + """ + Unique identifier for the project that the span iframe belongs under + """ + url: str + """ + URL to embed the project viewer in an iframe + """ + + +class DataSummary(TypedDict): + total_records: int + """ + Total number of records in the dataset + """ + + +class Dataset(TypedDict): + created: NotRequired[str | None] + """ + Date of dataset creation + """ + deleted_at: NotRequired[str | None] + """ + Date of dataset deletion, or null if the dataset is still active + """ + description: NotRequired[str | None] + """ + Textual description of the dataset + """ + id: str + """ + Unique identifier for the dataset + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + User-controlled metadata about the dataset + """ + name: str + """ + Name of the dataset. Within a project, dataset names are unique + """ + project_id: str + """ + Unique identifier for the project that the dataset belongs under + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the dataset + """ + url_slug: str + """ + URL slug for the dataset. used to construct dataset URLs + """ + user_id: NotRequired[str | None] + """ + Identifies the user who created the dataset + """ + + +class DatasetEventMetadata(TypedDict): + model: NotRequired[str | None] + """ + The model used for this example + """ + + +DatasetIdParam: TypeAlias = str +""" +Dataset id +""" + + +DatasetName: TypeAlias = str +""" +Name of the dataset to search for +""" + + +class DatasetSnapshot(TypedDict): + created: str | None + """ + Date of dataset snapshot creation + """ + dataset_id: str + """ + Unique identifier for the dataset that this snapshot belongs to + """ + description: str | None + id: str + """ + Unique identifier for the dataset snapshot + """ + name: str + """ + Name of the dataset snapshot + """ + xact_id: str + """ + Transaction id of the brainstore version at the time of the snapshot + """ + + +DatasetSnapshotIdParam: TypeAlias = str +""" +DatasetSnapshot id +""" + + +DatasetSnapshotName: TypeAlias = str +""" +Name of the dataset_snapshot to search for +""" + + +class DeleteAISecret(TypedDict): + name: str + """ + Name of the AI secret + """ + org_name: NotRequired[str | None] + """ + For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the AI Secret belongs in. + """ + + +class DeleteServiceToken(TypedDict): + id: str + """ + Unique identifier for the service token. + """ + + +class DeleteView(TypedDict): + object_id: str + """ + The id of the object the view applies to + """ + object_type: AclObjectType + + +EndingBefore: TypeAlias = str +""" +Pagination cursor id. + +For example, if the initial item in the last page you fetched had an id of `foo`, pass `ending_before=foo` to fetch the previous page. Note: you may only pass one of `starting_after` and `ending_before` +""" + + +class EnvVar(TypedDict): + created: NotRequired[str | None] + """ + Date of environment variable creation + """ + id: str + """ + Unique identifier for the environment variable + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + Optional metadata associated with the environment variable when managed via the function secrets API + """ + name: str + """ + The name of the environment variable + """ + object_id: str + """ + The id of the object the environment variable is scoped for + """ + object_type: Literal["organization", "project", "function"] + """ + The type of the object the environment variable is scoped for + """ + preview_secret: NotRequired[str | None] + """ + Redacted preview of the stored secret value + """ + secret_category: NotRequired[Literal["env_var", "ai_provider", "sandbox_provider"]] + """ + The category of the secret: env_var for regular environment variables, ai_provider for AI provider API keys + """ + secret_type: NotRequired[str | None] + """ + Optional classification for the secret (for example, the AI provider name) + """ + secret_updated_at: NotRequired[str | None] + """ + Date of last update to the encrypted secret value itself + """ + secret_updated_by_user_id: NotRequired[str | None] + """ + User id of the last update to the encrypted secret value + """ + used: NotRequired[str | None] + """ + Date the environment variable was last used + """ + + +EnvVarIdParam: TypeAlias = str +""" +EnvVar id +""" + + +EnvVarName: TypeAlias = str +""" +Name of the env_var to search for +""" + + +EnvVarObjectId: TypeAlias = str +""" +The id of the object the environment variable is scoped for +""" + + +EnvVarObjectType: TypeAlias = Literal["organization", "project", "function"] +""" +The type of the object the environment variable is scoped for +""" + + +class Environment(TypedDict): + created: NotRequired[str | None] + """ + Date of environment creation + """ + deleted_at: NotRequired[str | None] + """ + Date of environment deletion, or null if the environment is still active + """ + description: NotRequired[str | None] + """ + Textual description of the environment + """ + id: str + """ + Unique identifier for the environment + """ + name: str + """ + Name of the environment + """ + org_id: str + """ + Unique identifier for the organization that the environment belongs under + """ + slug: str + """ + A url-friendly, unique identifier for the environment within an organization + """ + + +class ExperimentInternalMetadata(TypedDict): + dataset_filter: NotRequired[Mapping[str, Any] | None] + """ + BTQL filter payload used to evaluate a subset of a linked dataset. + """ + + +class ExperimentEventContext(TypedDict): + caller_filename: NotRequired[str | None] + """ + Name of the file in code where the experiment event was created + """ + caller_functionname: NotRequired[str | None] + """ + The function in code which created the experiment event + """ + caller_lineno: NotRequired[int | None] + """ + Line of code where the experiment event was created + """ + + +class ExperimentEventMetadata(TypedDict): + model: NotRequired[str | None] + """ + The model used for this example + """ + + +class ExperimentEventMetrics(TypedDict): + caller_filename: NotRequired[Any | None] + """ + This metric is deprecated + """ + caller_functionname: NotRequired[Any | None] + """ + This metric is deprecated + """ + caller_lineno: NotRequired[Any | None] + """ + This metric is deprecated + """ + completion_tokens: NotRequired[int | None] + """ + The number of tokens in the completion generated by the model (only set if this is an LLM span) + """ + end: NotRequired[float | None] + """ + A unix timestamp recording when the section of code which produced the experiment event finished + """ + prompt_tokens: NotRequired[int | None] + """ + The number of tokens in the prompt used to generate the experiment event (only set if this is an LLM span) + """ + start: NotRequired[float | None] + """ + A unix timestamp recording when the section of code which produced the experiment event started + """ + tokens: NotRequired[int | None] + """ + The total number of tokens in the input and output of the experiment event. + """ + + +ExperimentIdParam: TypeAlias = str +""" +Experiment id +""" + + +ExperimentName: TypeAlias = str +""" +Name of the experiment to search for +""" + + +class Preprocessor1Preprocessor1(TypedDict): + id: str + type: Literal["function"] + version: NotRequired[str] + """ + The version of the function + """ + + +class Preprocessor1Preprocessor12(TypedDict): + pass + + +class Preprocessor1Preprocessor13(Preprocessor1Preprocessor1, Preprocessor1Preprocessor12): + pass + + +class FeedbackDatasetItem(TypedDict): + comment: NotRequired[str | None] + """ + An optional comment string to log about the dataset event + """ + id: str + """ + The id of the dataset event to log feedback for. This is the row `id` returned by `POST /v1/dataset/{dataset_id}/insert` + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + A dictionary with additional data about the feedback. If you have a `user_id`, you can log it here and access it in the Braintrust UI. Note, this metadata does not correspond to the main event itself, but rather the audit log attached to the event. + """ + source: NotRequired[Literal["app", "api", "external"] | None] + """ + The source of the feedback. Must be one of "external" (default), "app", or "api" + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags to log + """ + + +class FeedbackExperimentItem(TypedDict): + comment: NotRequired[str | None] + """ + An optional comment string to log about the experiment event + """ + expected: NotRequired[Any | None] + """ + The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not + """ + id: str + """ + The id of the experiment event to log feedback for. This is the row `id` returned by `POST /v1/experiment/{experiment_id}/insert` + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + A dictionary with additional data about the feedback. If you have a `user_id`, you can log it here and access it in the Braintrust UI. Note, this metadata does not correspond to the main event itself, but rather the audit log attached to the event. + """ + scores: NotRequired[Mapping[str, float | None] | None] + """ + A dictionary of numeric values (between 0 and 1) to log. These scores will be merged into the existing scores for the experiment event + """ + source: NotRequired[Literal["app", "api", "external"] | None] + """ + The source of the feedback. Must be one of "external" (default), "app", or "api" + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags to log + """ + + +class FeedbackProjectLogsItem(TypedDict): + comment: NotRequired[str | None] + """ + An optional comment string to log about the project logs event + """ + expected: NotRequired[Any | None] + """ + The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not + """ + id: str + """ + The id of the project logs event to log feedback for. This is the row `id` returned by `POST /v1/project_logs/{project_id}/insert` + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + A dictionary with additional data about the feedback. If you have a `user_id`, you can log it here and access it in the Braintrust UI. Note, this metadata does not correspond to the main event itself, but rather the audit log attached to the event. + """ + scores: NotRequired[Mapping[str, float | None] | None] + """ + A dictionary of numeric values (between 0 and 1) to log. These scores will be merged into the existing scores for the project logs event + """ + source: NotRequired[Literal["app", "api", "external"] | None] + """ + The source of the feedback. Must be one of "external" (default), "app", or "api" + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags to log + """ + + +class FeedbackResponseSchema(TypedDict): + status: Literal["success"] + + +FetchLimit: TypeAlias = int | None +""" +limit the number of traces fetched + +Fetch queries may be paginated if the total result size is expected to be large (e.g. project_logs which accumulate over a long time). Note that fetch queries only support pagination in descending time order (from latest to earliest `_xact_id`. Furthermore, later pages may return rows which showed up in earlier pages, except with an earlier `_xact_id`. This happens because pagination occurs over the whole version history of the event log. You will most likely want to exclude any such duplicate, outdated rows (by `id`) from your combined result set. + +The `limit` parameter controls the number of full traces to return. So you may end up with more individual rows than the specified limit if you are fetching events containing traces. +""" + + +FetchLimitParam: TypeAlias = int | None +""" +limit the number of traces fetched + +Fetch queries may be paginated if the total result size is expected to be large (e.g. project_logs which accumulate over a long time). Note that fetch queries only support pagination in descending time order (from latest to earliest `_xact_id`. Furthermore, later pages may return rows which showed up in earlier pages, except with an earlier `_xact_id`. This happens because pagination occurs over the whole version history of the event log. You will most likely want to exclude any such duplicate, outdated rows (by `id`) from your combined result set. + +The `limit` parameter controls the number of full traces to return. So you may end up with more individual rows than the specified limit if you are fetching events containing traces. +""" + + +FetchPaginationCursor: TypeAlias = str | None +""" +An opaque string to be used as a cursor for the next page of results, in order from latest to earliest. + +The string can be obtained directly from the `cursor` property of the previous fetch query +""" + + +class FunctionFunctionSchema(TypedDict): + parameters: NotRequired[Any | None] + returns: NotRequired[Any | None] + + +class FunctionOrigin(TypedDict): + internal: NotRequired[bool | None] + """ + The function exists for internal purposes and should not be displayed in the list of functions. + """ + object_id: str + """ + Id of the object the function is originating from + """ + object_type: AclObjectType + + +class FunctionDataFunctionData(TypedDict): + type: Literal["prompt"] + + +class Data(CodeBundle): + type: Literal["bundle"] + + +class FunctionDataFunctionData1DataRuntimeContext(TypedDict): + runtime: Literal["node", "python", "browser", "quickjs"] + version: str + + +class FunctionDataFunctionData1Data(TypedDict): + code: str + code_hash: NotRequired[str] + """ + SHA256 hash of the code, computed at save time + """ + runtime_context: FunctionDataFunctionData1DataRuntimeContext + type: Literal["inline"] + + +class FunctionDataFunctionData1(TypedDict): + data: Data | FunctionDataFunctionData1Data + type: Literal["code"] + + +class FunctionDataFunctionData2(TypedDict): + endpoint: str + eval_name: str + parameters: Mapping[str, Any] + parameters_version: NotRequired[str | None] + """ + The version (transaction ID) of the parameters being used + """ + type: Literal["remote_eval"] + + +class FunctionDataFunctionData4FieldSchema(TypedDict): + additionalProperties: NotRequired[bool] + properties: Mapping[str, Mapping[str, Any]] + required: NotRequired[Sequence[str]] + type: Literal["object"] + + +class FunctionDataFunctionData4(TypedDict): + field__schema: FunctionDataFunctionData4FieldSchema + """ + JSON Schema format for parameters + """ + data: Mapping[str, Any] + """ + The parameters data + """ + type: Literal["parameters"] + + +class FunctionDataNullishFunctionDataNullish(TypedDict): + type: Literal["prompt"] + + +class FunctionDataNullishFunctionDataNullish1DataRuntimeContext(TypedDict): + runtime: Literal["node", "python", "browser", "quickjs"] + version: str + + +class FunctionDataNullishFunctionDataNullish1Data(TypedDict): + code: str + code_hash: NotRequired[str] + """ + SHA256 hash of the code, computed at save time + """ + runtime_context: FunctionDataNullishFunctionDataNullish1DataRuntimeContext + type: Literal["inline"] + + +class FunctionDataNullishFunctionDataNullish1(TypedDict): + data: Data | FunctionDataNullishFunctionDataNullish1Data + type: Literal["code"] + + +class FunctionDataNullishFunctionDataNullish2(TypedDict): + endpoint: str + eval_name: str + parameters: Mapping[str, Any] + parameters_version: NotRequired[str | None] + """ + The version (transaction ID) of the parameters being used + """ + type: Literal["remote_eval"] + + +class FunctionDataNullishFunctionDataNullish4FieldSchema(TypedDict): + additionalProperties: NotRequired[bool] + properties: Mapping[str, Mapping[str, Any]] + required: NotRequired[Sequence[str]] + type: Literal["object"] + + +class FunctionDataNullishFunctionDataNullish4(TypedDict): + field__schema: FunctionDataNullishFunctionDataNullish4FieldSchema + """ + JSON Schema format for parameters + """ + data: Mapping[str, Any] + """ + The parameters data + """ + type: Literal["parameters"] + + +class FunctionIdFunctionId(TypedDict): + function_id: str + """ + The ID of the function + """ + version: NotRequired[str] + """ + The version of the function + """ + + +class FunctionIdFunctionId1(TypedDict): + project_name: str + """ + The name of the project containing the function + """ + slug: str + """ + The slug of the function + """ + version: NotRequired[str] + """ + The version of the function + """ + + +class FunctionIdFunctionId3(TypedDict): + prompt_session_function_id: str + """ + The ID of the function in the prompt session + """ + prompt_session_id: str + """ + The ID of the prompt session + """ + version: NotRequired[str] + """ + The version of the function + """ + + +class FunctionIdFunctionId4InlineContext(TypedDict): + runtime: Literal["node", "python", "browser", "quickjs"] + version: str + + +FunctionIdParam: TypeAlias = str +""" +Function id +""" + + +FunctionIdRef: TypeAlias = Mapping[str, Any] + + +FunctionName: TypeAlias = str +""" +Name of the function to search for +""" + + +FunctionTypeEnum: TypeAlias = ( + Literal[ + "llm", + "scorer", + "task", + "tool", + "custom_view", + "preprocessor", + "facet", + "classifier", + "tag", + "parameters", + "sandbox", + ] + | None +) +""" +The type of global function. Defaults to 'scorer'. +""" + + +FunctionTypeEnumNullish: TypeAlias = ( + Literal[ + "llm", + "scorer", + "task", + "tool", + "custom_view", + "preprocessor", + "facet", + "classifier", + "tag", + "parameters", + "sandbox", + ] + | None +) + + +class GitMetadataSettings(TypedDict): + collect: Literal["all", "none", "some"] + fields: NotRequired[ + Sequence[ + Literal[ + "commit", + "branch", + "tag", + "dirty", + "author_name", + "author_email", + "commit_message", + "commit_time", + "git_diff", + ] + ] + ] + + +class GraphEdgeSource(TypedDict): + node: str + """ + The id of the node in the graph + """ + variable: str + + +class GraphEdgeTarget(TypedDict): + node: str + """ + The id of the node in the graph + """ + variable: str + + +class GraphEdge(TypedDict): + purpose: Literal["control", "data", "messages"] + """ + The purpose of the edge + """ + source: GraphEdgeSource + target: GraphEdgeTarget + + +class GraphNodeGraphNodePosition(TypedDict): + x: float + """ + The x position of the node + """ + y: float + """ + The y position of the node + """ + + +class GraphNodeGraphNode(TypedDict): + description: NotRequired[str | None] + """ + The description of the node + """ + function: FunctionIdRef + position: NotRequired[GraphNodeGraphNodePosition | None] + """ + The position of the node + """ + type: Literal["function"] + + +class GraphNodeGraphNode1Position(TypedDict): + x: float + """ + The x position of the node + """ + y: float + """ + The y position of the node + """ + + +class GraphNodeGraphNode1(TypedDict): + description: NotRequired[str | None] + """ + The description of the node + """ + position: NotRequired[GraphNodeGraphNode1Position | None] + """ + The position of the node + """ + type: Literal["input"] + """ + The input to the graph + """ + + +class GraphNodeGraphNode2Position(TypedDict): + x: float + """ + The x position of the node + """ + y: float + """ + The y position of the node + """ + + +class GraphNodeGraphNode2(TypedDict): + description: NotRequired[str | None] + """ + The description of the node + """ + position: NotRequired[GraphNodeGraphNode2Position | None] + """ + The position of the node + """ + type: Literal["output"] + """ + The output of the graph + """ + + +class GraphNodeGraphNode3Position(TypedDict): + x: float + """ + The x position of the node + """ + y: float + """ + The y position of the node + """ + + +class GraphNodeGraphNode3(TypedDict): + description: NotRequired[str | None] + """ + The description of the node + """ + position: NotRequired[GraphNodeGraphNode3Position | None] + """ + The position of the node + """ + type: Literal["literal"] + value: NotRequired[Any | None] + """ + A literal value to be returned + """ + + +class GraphNodeGraphNode4Position(TypedDict): + x: float + """ + The x position of the node + """ + y: float + """ + The y position of the node + """ + + +class GraphNodeGraphNode4(TypedDict): + description: NotRequired[str | None] + """ + The description of the node + """ + expr: str + """ + A BTQL expression to be evaluated + """ + position: NotRequired[GraphNodeGraphNode4Position | None] + """ + The position of the node + """ + type: Literal["btql"] + + +class GraphNodeGraphNode5Position(TypedDict): + x: float + """ + The x position of the node + """ + y: float + """ + The y position of the node + """ + + +class GraphNodeGraphNode5(TypedDict): + condition: NotRequired[str | None] + """ + A BTQL expression to be evaluated + """ + description: NotRequired[str | None] + """ + The description of the node + """ + position: NotRequired[GraphNodeGraphNode5Position | None] + """ + The position of the node + """ + type: Literal["gate"] + + +class GraphNodeGraphNode6Position(TypedDict): + x: float + """ + The x position of the node + """ + y: float + """ + The y position of the node + """ + + +class GraphNodeGraphNode6(TypedDict): + description: NotRequired[str | None] + """ + The description of the node + """ + position: NotRequired[GraphNodeGraphNode6Position | None] + """ + The position of the node + """ + type: Literal["aggregator"] + + +class GraphNodeGraphNode7Position(TypedDict): + x: float + """ + The x position of the node + """ + y: float + """ + The y position of the node + """ + + +class Group(TypedDict): + created: NotRequired[str | None] + """ + Date of group creation + """ + deleted_at: NotRequired[str | None] + """ + Date of group deletion, or null if the group is still active + """ + description: NotRequired[str | None] + """ + Textual description of the group + """ + id: str + """ + Unique identifier for the group + """ + member_groups: NotRequired[Sequence[str] | None] + """ + Ids of the groups this group inherits from + + An inheriting group has all the users contained in its member groups, as well as all of their inherited users + """ + member_users: NotRequired[Sequence[str] | None] + """ + Ids of users which belong to this group + """ + name: str + """ + Name of the group + """ + org_id: str + """ + Unique id for the organization that the group belongs under + + It is forbidden to change the org after creating a group + """ + user_id: NotRequired[str | None] + """ + Identifies the user who created the group + """ + + +GroupIdParam: TypeAlias = str +""" +Group id +""" + + +GroupName: TypeAlias = str +""" +Name of the group to search for +""" + + +class GroupScope(TypedDict): + group_by: str + """ + Field path to group by, e.g. metadata.session_id + """ + idle_seconds: NotRequired[float] + """ + Optional: trigger after this many seconds of inactivity + """ + interval_seconds: NotRequired[float] + """ + Maximum time range to include when constructing a group + """ + max_traces: NotRequired[int] + """ + Maximum number of traces to include when constructing a group (default/max: 64) + """ + placement: Literal["first", "each"] + """ + Which trace or traces to write grouped scorer results to + """ + type: Literal["group"] + + +Ids: TypeAlias = str | Sequence[str] +""" +Filter search results to a particular set of object IDs. To specify a list of IDs, include the query param multiple times +""" + + +ImageRenderingMode: TypeAlias = Literal["auto", "click_to_load", "blocked"] | None +""" +Controls how images are rendered in the UI: 'auto' loads images automatically, 'click_to_load' shows a placeholder until clicked, 'blocked' prevents image loading entirely +""" + + +class InsertDatasetEventFieldArrayDeleteItem(TypedDict): + delete: Sequence[Any] + path: Sequence[str] + + +class InsertDatasetEventMetadata(TypedDict): + model: NotRequired[str | None] + """ + The model used for this example + """ + + +class InsertEventsResponse(TypedDict): + row_ids: Sequence[str] + """ + The ids of all rows that were inserted, aligning one-to-one with the rows provided as input + """ + + +class InsertExperimentEventFieldArrayDeleteItem(TypedDict): + delete: Sequence[Any] + path: Sequence[str] + + +class InsertExperimentEventContext(TypedDict): + caller_filename: NotRequired[str | None] + """ + Name of the file in code where the experiment event was created + """ + caller_functionname: NotRequired[str | None] + """ + The function in code which created the experiment event + """ + caller_lineno: NotRequired[int | None] + """ + Line of code where the experiment event was created + """ + + +class InsertExperimentEventMetadata(TypedDict): + model: NotRequired[str | None] + """ + The model used for this example + """ + + +class InsertExperimentEventMetrics(TypedDict): + caller_filename: NotRequired[Any | None] + """ + This metric is deprecated + """ + caller_functionname: NotRequired[Any | None] + """ + This metric is deprecated + """ + caller_lineno: NotRequired[Any | None] + """ + This metric is deprecated + """ + completion_tokens: NotRequired[int | None] + """ + The number of tokens in the completion generated by the model (only set if this is an LLM span) + """ + end: NotRequired[float | None] + """ + A unix timestamp recording when the section of code which produced the experiment event finished + """ + prompt_tokens: NotRequired[int | None] + """ + The number of tokens in the prompt used to generate the experiment event (only set if this is an LLM span) + """ + start: NotRequired[float | None] + """ + A unix timestamp recording when the section of code which produced the experiment event started + """ + tokens: NotRequired[int | None] + """ + The total number of tokens in the input and output of the experiment event. + """ + + +class InsertProjectLogsEventFieldArrayDeleteItem(TypedDict): + delete: Sequence[Any] + path: Sequence[str] + + +class InsertProjectLogsEventContext(TypedDict): + caller_filename: NotRequired[str | None] + """ + Name of the file in code where the project logs event was created + """ + caller_functionname: NotRequired[str | None] + """ + The function in code which created the project logs event + """ + caller_lineno: NotRequired[int | None] + """ + Line of code where the project logs event was created + """ + + +class InsertProjectLogsEventMetadata(TypedDict): + model: NotRequired[str | None] + """ + The model used for this example + """ + + +class InsertProjectLogsEventMetrics(TypedDict): + caller_filename: NotRequired[Any | None] + """ + This metric is deprecated + """ + caller_functionname: NotRequired[Any | None] + """ + This metric is deprecated + """ + caller_lineno: NotRequired[Any | None] + """ + This metric is deprecated + """ + completion_tokens: NotRequired[int | None] + """ + The number of tokens in the completion generated by the model (only set if this is an LLM span) + """ + end: NotRequired[float | None] + """ + A unix timestamp recording when the section of code which produced the project logs event finished + """ + prompt_tokens: NotRequired[int | None] + """ + The number of tokens in the prompt used to generate the project logs event (only set if this is an LLM span) + """ + start: NotRequired[float | None] + """ + A unix timestamp recording when the section of code which produced the project logs event started + """ + tokens: NotRequired[int | None] + """ + The total number of tokens in the input and output of the project logs event. + """ + + +class InvokeApiMcpAuth(TypedDict): + oauth_token: NotRequired[str] + """ + The OAuth token to use + """ + + +class InvokeParentInvokeParentRowIds(TypedDict): + id: str + """ + The id of the row + """ + root_span_id: str + """ + The root_span_id of the row + """ + span_id: str + """ + The span_id of the row + """ + + +class InvokeParentInvokeParent(TypedDict): + object_id: str + """ + The id of the container object you are logging to + """ + object_type: Literal["project_logs", "experiment", "playground_logs"] + propagated_event: NotRequired[Mapping[str, Any] | None] + """ + Include these properties in every span created under this parent + """ + row_ids: NotRequired[InvokeParentInvokeParentRowIds | None] + """ + Identifiers for the row to to log a subspan under + """ + + +InvokeParent: TypeAlias = InvokeParentInvokeParent | str +""" +Options for tracing the function call +""" + + +class MCPServer(TypedDict): + created: NotRequired[str | None] + """ + Date of MCP server creation + """ + deleted_at: NotRequired[str | None] + """ + Date of MCP server deletion, or null if the MCP server is still active + """ + description: NotRequired[str | None] + """ + Textual description of the MCP server + """ + id: str + """ + Unique identifier for the MCP server + """ + name: str + """ + Name of the MCP server. Within a project, MCP server names are unique + """ + project_id: str + """ + Unique identifier for the project that the MCP server belongs under + """ + url: str + """ + URL of the MCP server endpoint + """ + user_id: NotRequired[str | None] + """ + Identifies the user who created the MCP server + """ + + +MaxRootSpanId: TypeAlias = str +""" +DEPRECATION NOTICE: The manually-constructed pagination cursor is deprecated in favor of the explicit 'cursor' returned by object fetch requests. Please prefer the 'cursor' argument going forwards. + +Together, `max_xact_id` and `max_root_span_id` form a pagination cursor + +Since a paginated fetch query returns results in order from latest to earliest, the cursor for the next page can be found as the row with the minimum (earliest) value of the tuple `(_xact_id, root_span_id)`. See the documentation of `limit` for an overview of paginating fetch queries. +""" + + +MaxXactId: TypeAlias = str +""" +DEPRECATION NOTICE: The manually-constructed pagination cursor is deprecated in favor of the explicit 'cursor' returned by object fetch requests. Please prefer the 'cursor' argument going forwards. + +Together, `max_xact_id` and `max_root_span_id` form a pagination cursor + +Since a paginated fetch query returns results in order from latest to earliest, the cursor for the next page can be found as the row with the minimum (earliest) value of the tuple `(_xact_id, root_span_id)`. See the documentation of `limit` for an overview of paginating fetch queries. +""" + + +McpServerIdParam: TypeAlias = str +""" +McpServer id +""" + + +McpServerName: TypeAlias = str +""" +Name of the mcp_server to search for +""" + + +class MetricSummary(TypedDict): + diff: NotRequired[float] + """ + Difference in metric between the current and comparison experiment + """ + improvements: int + """ + Number of improvements in the metric + """ + metric: float + """ + Average metric across all examples + """ + name: str + """ + Name of the metric + """ + regressions: int + """ + Number of regressions in the metric + """ + unit: str + """ + Unit label for the metric + """ + + +class ModelParamsModelParamsFunctionCall(TypedDict): + name: str + + +class ModelParamsModelParamsToolChoiceFunction(TypedDict): + name: str + + +class ModelParamsModelParamsToolChoice(TypedDict): + function: ModelParamsModelParamsToolChoiceFunction + type: Literal["function"] + + +class ModelParamsModelParams1(TypedDict): + max_tokens: float + max_tokens_to_sample: NotRequired[float] + """ + This is a legacy parameter that should not be used. + """ + reasoning_budget: NotRequired[float] + reasoning_enabled: NotRequired[bool] + stop_sequences: NotRequired[Sequence[str]] + temperature: float + top_k: NotRequired[float] + top_p: NotRequired[float] + use_cache: NotRequired[bool] + + +class ModelParamsModelParams2(TypedDict): + maxOutputTokens: NotRequired[float] + reasoning_budget: NotRequired[float] + reasoning_enabled: NotRequired[bool] + temperature: NotRequired[float] + topK: NotRequired[float] + topP: NotRequired[float] + use_cache: NotRequired[bool] + + +class ModelParamsModelParams3(TypedDict): + reasoning_budget: NotRequired[float] + reasoning_enabled: NotRequired[bool] + temperature: NotRequired[float] + topK: NotRequired[float] + use_cache: NotRequired[bool] + + +class ModelParamsModelParams4(TypedDict): + reasoning_budget: NotRequired[float] + reasoning_enabled: NotRequired[bool] + use_cache: NotRequired[bool] + + +class NullableSavedFunctionIdNullableSavedFunctionId(TypedDict): + id: str + type: Literal["function"] + version: NotRequired[str] + """ + The version of the function + """ + + +class NullableSavedFunctionIdNullableSavedFunctionId1(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + name: str + type: Literal["global"] + + +NullableSavedFunctionId: TypeAlias = ( + NullableSavedFunctionIdNullableSavedFunctionId | NullableSavedFunctionIdNullableSavedFunctionId1 | None +) +""" +Default preprocessor for this project. When set, functions that use preprocessors will use this instead of their built-in default. +""" + + +class ObjectReferenceNullish(TypedDict): + field_xact_id: NotRequired[str | None] + """ + Transaction ID of the original event. + """ + created: NotRequired[str | None] + """ + Created timestamp of the original event. Used to help sort in the UI + """ + id: str + """ + ID of the original event. + """ + object_id: str + """ + ID of the object the event is originating from. + """ + object_type: Literal["project_logs", "experiment", "dataset", "prompt", "function", "prompt_session"] + """ + Type of the object the event is originating from. + """ + + +class ScorerScorer(TypedDict): + id: str + type: Literal["function"] + version: NotRequired[str] + """ + The version of the function + """ + + +class ScorerScorer1(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + name: str + type: Literal["global"] + + +class ScorerScorer2(TypedDict): + pass + + +class ScorerScorer3(ScorerScorer, ScorerScorer2): + pass + + +class ScorerScorer4(ScorerScorer1, ScorerScorer2): + pass + + +class ScorerScorer5(ScorerScorer, ScorerScorer2): + pass + + +class ScorerScorer6(ScorerScorer1, ScorerScorer2): + pass + + +Scorer: TypeAlias = ScorerScorer3 | ScorerScorer4 | ScorerScorer5 | ScorerScorer6 + + +OrgName: TypeAlias = str +""" +Filter search results to within a particular organization +""" + + +class Organization(TypedDict): + api_url: NotRequired[str | None] + created: NotRequired[str | None] + """ + Date of organization creation + """ + id: str + """ + Unique identifier for the organization + """ + image_rendering_mode: NotRequired[ImageRenderingMode | None] + is_dataplane_private: NotRequired[bool | None] + is_universal_api: NotRequired[bool | None] + name: str + """ + Name of the organization + """ + proxy_url: NotRequired[str | None] + realtime_url: NotRequired[str | None] + + +OrganizationIdParam: TypeAlias = str +""" +Organization id +""" + + +class PatchAISecret(TypedDict): + metadata: NotRequired[Mapping[str, Any] | None] + name: NotRequired[str | None] + """ + Name of the AI secret + """ + secret: NotRequired[str | None] + type: NotRequired[str | None] + + +class PatchAgent(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the agent + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + User-controlled metadata about the agent + """ + name: NotRequired[str | None] + """ + Name of the agent. Within a project, agent names are unique + """ + + +class PatchDataset(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the dataset + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + User-controlled metadata about the dataset + """ + name: NotRequired[str | None] + """ + Name of the dataset. Within a project, dataset names are unique + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the dataset + """ + + +class PatchDatasetSnapshot(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the dataset snapshot + """ + name: NotRequired[str | None] + """ + Name of the dataset snapshot + """ + + +class PatchEnvironment(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the environment + """ + name: NotRequired[str | None] + """ + Name of the environment + """ + slug: NotRequired[str | None] + """ + A url-friendly, unique identifier for the environment within an organization + """ + + +class PatchExperimentInternalMetadata(TypedDict): + dataset_filter: NotRequired[Mapping[str, Any] | None] + """ + BTQL filter payload used to evaluate a subset of a linked dataset. + """ + + +class PatchGroup(TypedDict): + add_member_groups: NotRequired[Sequence[str] | None] + """ + A list of group IDs to add to the group's inheriting-from set + """ + add_member_users: NotRequired[Sequence[str] | None] + """ + A list of user IDs to add to the group + """ + description: NotRequired[str | None] + """ + Textual description of the group + """ + name: NotRequired[str | None] + """ + Name of the group + """ + remove_member_groups: NotRequired[Sequence[str] | None] + """ + A list of group IDs to remove from the group's inheriting-from set + """ + remove_member_users: NotRequired[Sequence[str] | None] + """ + A list of user IDs to remove from the group + """ + + +class PatchMCPServer(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the MCP server + """ + name: NotRequired[str | None] + """ + Name of the MCP server. Within a project, MCP server names are unique + """ + url: NotRequired[str | None] + """ + URL of the MCP server endpoint + """ + + +class PatchOrganization(TypedDict): + api_url: NotRequired[str | None] + image_rendering_mode: NotRequired[ImageRenderingMode | None] + is_dataplane_private: NotRequired[bool | None] + is_universal_api: NotRequired[bool | None] + name: NotRequired[str | None] + """ + Name of the organization + """ + proxy_url: NotRequired[str | None] + realtime_url: NotRequired[str | None] + + +class PatchOrganizationMembersInviteUsersServiceAccount(TypedDict): + name: str + token_name: NotRequired[str | None] + """ + Optional name of an initial service token to create for the new service account. When this field is set, the request must be authenticated with a service token that has organization-owner permissions, not a user API key. + """ + + +class PatchOrganizationMembersInviteUsers(TypedDict): + emails: NotRequired[Sequence[str] | None] + """ + Emails of users to invite + """ + group_id: NotRequired[str | None] + """ + Singular form of group_ids + """ + group_ids: NotRequired[Sequence[str] | None] + """ + Optional list of group ids to add newly-invited users to. + """ + group_name: NotRequired[str | None] + """ + Singular form of group_names + """ + group_names: NotRequired[Sequence[str] | None] + """ + Optional list of group names to add newly-invited users to. + """ + ids: NotRequired[Sequence[str] | None] + """ + Ids of existing users to invite + """ + send_invite_emails: NotRequired[bool | None] + """ + If true, send invite emails to the users who wore actually added + """ + service_accounts: NotRequired[Sequence[PatchOrganizationMembersInviteUsersServiceAccount] | None] + """ + Service accounts to create. Any caller permitted to add organization members can create service accounts (but not necessarily their associated tokens). + """ + + +class PatchOrganizationMembersRemoveUsers(TypedDict): + emails: NotRequired[Sequence[str] | None] + """ + Emails of users to remove + """ + ids: NotRequired[Sequence[str] | None] + """ + Ids of users to remove + """ + + +class PatchOrganizationMembers(TypedDict): + invite_users: NotRequired[PatchOrganizationMembersInviteUsers | None] + """ + Users to invite to the organization + """ + org_id: NotRequired[str | None] + """ + For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, or in case you want to explicitly assert the organization you are modifying, you may specify the id of the organization. + """ + org_name: NotRequired[str | None] + """ + For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, or in case you want to explicitly assert the organization you are modifying, you may specify the name of the organization. + """ + remove_users: NotRequired[PatchOrganizationMembersRemoveUsers | None] + """ + Users to remove from the organization + """ + + +class PatchOrganizationMembersOutputAddedUser(TypedDict): + api_key: NotRequired[str | None] + email: NotRequired[str | None] + id: str + token_name: NotRequired[str | None] + + +class PatchOrganizationMembersOutput(TypedDict): + added_users: NotRequired[Sequence[PatchOrganizationMembersOutputAddedUser] | None] + """ + If service accounts with tokens were created, this will contain the added users with their API keys + """ + org_id: str + """ + The id of the org that was modified. + """ + send_email_error: NotRequired[str | None] + """ + If invite emails failed to send for some reason, the patch operation will still complete, but we will return an error message here + """ + status: Literal["success"] + + +class PatchProjectAutomationConfigAction(TypedDict): + type: Literal["webhook"] + """ + The type of action to take + """ + url: str + """ + The webhook URL to send the request to + """ + + +class PatchProjectAutomationConfigAction1(TypedDict): + channel: str + """ + The Slack channel ID to post to + """ + message_template: NotRequired[str] + """ + Custom message template for the alert + """ + type: Literal["slack"] + """ + The type of action to take + """ + workspace_id: str + """ + The Slack workspace ID to post to + """ + + +class PatchProjectAutomationConfig(TypedDict): + action: PatchProjectAutomationConfigAction | PatchProjectAutomationConfigAction1 + """ + The action to take when the automation rule is triggered + """ + btql_filter: str + """ + BTQL filter to identify rows for the automation rule + """ + event_type: Literal["logs"] + """ + The type of automation. + """ + interval_seconds: float + """ + Perform the triggered action at most once in this interval of seconds + """ + + +class PatchProjectAutomationConfig1Credentials(TypedDict): + external_id: str + """ + The automation-specific external id component (auto-generated by default) + """ + role_arn: str + """ + The ARN of the IAM role to use + """ + type: Literal["aws_iam"] + + +class PatchProjectAutomationConfig1Credentials1(TypedDict): + service_account_email: str + """ + The GCP service account email to impersonate + """ + type: Literal["gcp_service_account"] + + +class PatchProjectAutomationConfig1ExportDefinition(TypedDict): + type: Literal["log_traces"] + + +class PatchProjectAutomationConfig1ExportDefinition1(TypedDict): + type: Literal["log_spans"] + + +class PatchProjectAutomationConfig1ExportDefinition2(TypedDict): + btql_query: str + """ + The BTQL query to export + """ + type: Literal["btql_query"] + + +class PatchProjectAutomationConfig2(TypedDict): + batch_size: NotRequired[int | None] + """ + The maximum number of result rows to write per async query batch + """ + created_by_user_id: str + """ + The user who submitted the async query + """ + event_type: Literal["async_query"] + """ + The type of automation. + """ + format: Literal["jsonl"] + """ + The materialized result format + """ + object_id: str + """ + The source object ID for the async query + """ + object_type: Literal["project_logs", "experiment", "dataset", "playground_logs"] + """ + The source object type for the async query + """ + query: str + """ + The SQL query to execute asynchronously + """ + status: NotRequired[AutomationStatus] + + +class PatchProjectAutomationConfig4Action(TypedDict): + type: Literal["webhook"] + """ + The type of action to take + """ + url: str + """ + The webhook URL to send the request to + """ + + +class PatchProjectAutomationConfig4Action1(TypedDict): + channel: str + """ + The Slack channel ID to post to + """ + message_template: NotRequired[str] + """ + Custom message template for the alert + """ + type: Literal["slack"] + """ + The type of action to take + """ + workspace_id: str + """ + The Slack workspace ID to post to + """ + + +class PatchProjectAutomationConfig4(TypedDict): + action: PatchProjectAutomationConfig4Action | PatchProjectAutomationConfig4Action1 + """ + The action to take when the automation rule is triggered + """ + environment_filter: NotRequired[Sequence[str]] + """ + Optional list of environment slugs to filter by + """ + event_type: Literal["environment_update"] + """ + The type of automation. + """ + + +class PatchProjectTag(TypedDict): + color: NotRequired[str | None] + """ + Color of the tag for the UI + """ + description: NotRequired[str | None] + """ + Textual description of the project tag + """ + name: NotRequired[str | None] + """ + Name of the project tag + """ + + +class PatchSpanIFrame(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the span iframe + """ + name: NotRequired[str | None] + """ + Name of the span iframe + """ + post_message: NotRequired[bool | None] + """ + Whether to post messages to the iframe containing the span's data. This is useful when you want to render more data than fits in the URL. + """ + url: NotRequired[str | None] + """ + URL to embed the project viewer in an iframe + """ + + +Permission: TypeAlias = Literal[ + "create", + "read", + "update", + "delete", + "create_acls", + "read_acls", + "update_acls", + "delete_acls", +] +""" +Each permission permits a certain type of operation on an object in the system + +Permissions can be assigned to to objects on an individual basis, or grouped into roles +""" + + +class ProjectAutomationConfigAction(TypedDict): + type: Literal["webhook"] + """ + The type of action to take + """ + url: str + """ + The webhook URL to send the request to + """ + + +class ProjectAutomationConfigAction1(TypedDict): + channel: str + """ + The Slack channel ID to post to + """ + message_template: NotRequired[str] + """ + Custom message template for the alert + """ + type: Literal["slack"] + """ + The type of action to take + """ + workspace_id: str + """ + The Slack workspace ID to post to + """ + + +class ProjectAutomationConfig(TypedDict): + action: ProjectAutomationConfigAction | ProjectAutomationConfigAction1 + """ + The action to take when the automation rule is triggered + """ + btql_filter: str + """ + BTQL filter to identify rows for the automation rule + """ + event_type: Literal["logs"] + """ + The type of automation. + """ + interval_seconds: float + """ + Perform the triggered action at most once in this interval of seconds + """ + + +class ProjectAutomationConfig1Credentials(TypedDict): + external_id: str + """ + The automation-specific external id component (auto-generated by default) + """ + role_arn: str + """ + The ARN of the IAM role to use + """ + type: Literal["aws_iam"] + + +class ProjectAutomationConfig1Credentials1(TypedDict): + service_account_email: str + """ + The GCP service account email to impersonate + """ + type: Literal["gcp_service_account"] + + +class ProjectAutomationConfig1ExportDefinition(TypedDict): + type: Literal["log_traces"] + + +class ProjectAutomationConfig1ExportDefinition1(TypedDict): + type: Literal["log_spans"] + + +class ProjectAutomationConfig1ExportDefinition2(TypedDict): + btql_query: str + """ + The BTQL query to export + """ + type: Literal["btql_query"] + + +class ProjectAutomationConfig2(TypedDict): + batch_size: NotRequired[int | None] + """ + The maximum number of result rows to write per async query batch + """ + created_by_user_id: str + """ + The user who submitted the async query + """ + event_type: Literal["async_query"] + """ + The type of automation. + """ + format: Literal["jsonl"] + """ + The materialized result format + """ + object_id: str + """ + The source object ID for the async query + """ + object_type: Literal["project_logs", "experiment", "dataset", "playground_logs"] + """ + The source object type for the async query + """ + query: str + """ + The SQL query to execute asynchronously + """ + status: NotRequired[AutomationStatus] + + +class ProjectAutomationConfig4Action(TypedDict): + type: Literal["webhook"] + """ + The type of action to take + """ + url: str + """ + The webhook URL to send the request to + """ + + +class ProjectAutomationConfig4Action1(TypedDict): + channel: str + """ + The Slack channel ID to post to + """ + message_template: NotRequired[str] + """ + Custom message template for the alert + """ + type: Literal["slack"] + """ + The type of action to take + """ + workspace_id: str + """ + The Slack workspace ID to post to + """ + + +class ProjectAutomationConfig4(TypedDict): + action: ProjectAutomationConfig4Action | ProjectAutomationConfig4Action1 + """ + The action to take when the automation rule is triggered + """ + environment_filter: NotRequired[Sequence[str]] + """ + Optional list of environment slugs to filter by + """ + event_type: Literal["environment_update"] + """ + The type of automation. + """ + + +ProjectAutomationIdParam: TypeAlias = str +""" +ProjectAutomation id +""" + + +ProjectAutomationName: TypeAlias = str +""" +Name of the project_automation to search for +""" + + +ProjectIdParam: TypeAlias = str +""" +Project id +""" + + +ProjectIdQuery: TypeAlias = str +""" +Project id +""" + + +class ProjectLogsEventContext(TypedDict): + caller_filename: NotRequired[str | None] + """ + Name of the file in code where the project logs event was created + """ + caller_functionname: NotRequired[str | None] + """ + The function in code which created the project logs event + """ + caller_lineno: NotRequired[int | None] + """ + Line of code where the project logs event was created + """ + + +class ProjectLogsEventMetadata(TypedDict): + model: NotRequired[str | None] + """ + The model used for this example + """ + + +class ProjectLogsEventMetrics(TypedDict): + caller_filename: NotRequired[Any | None] + """ + This metric is deprecated + """ + caller_functionname: NotRequired[Any | None] + """ + This metric is deprecated + """ + caller_lineno: NotRequired[Any | None] + """ + This metric is deprecated + """ + completion_tokens: NotRequired[int | None] + """ + The number of tokens in the completion generated by the model (only set if this is an LLM span) + """ + end: NotRequired[float | None] + """ + A unix timestamp recording when the section of code which produced the project logs event finished + """ + prompt_tokens: NotRequired[int | None] + """ + The number of tokens in the prompt used to generate the project logs event (only set if this is an LLM span) + """ + start: NotRequired[float | None] + """ + A unix timestamp recording when the section of code which produced the project logs event started + """ + tokens: NotRequired[int | None] + """ + The total number of tokens in the input and output of the project logs event. + """ + + +ProjectName: TypeAlias = str +""" +Name of the project to search for +""" + + +class ProjectScoreCategory(TypedDict): + name: str + """ + Name of the category + """ + value: float + """ + Numerical value of the category. Must be between 0 and 1, inclusive + """ + + +class ProjectScoreConditionWhen(TypedDict): + clauses: NotRequired[Sequence[str] | None] + subspan_clauses: NotRequired[Sequence[str] | None] + trace_clauses: NotRequired[Sequence[str] | None] + + +class ProjectScoreCondition(TypedDict): + behavior: NotRequired[Literal["hidden"]] + when: ProjectScoreConditionWhen + + +class ProjectScoreConfigVisibility(TypedDict): + groups: NotRequired[Sequence[str] | None] + users: NotRequired[Sequence[str] | None] + + +ProjectScoreIdParam: TypeAlias = str +""" +ProjectScore id +""" + + +ProjectScoreName: TypeAlias = str +""" +Name of the project_score to search for +""" + + +ProjectScoreType: TypeAlias = Literal["slider", "categorical", "weighted", "minimum", "maximum", "online", "free-form"] +""" +The type of the configured score +""" + + +class ProjectSettingsRemoteEvalSource(TypedDict): + description: NotRequired[str | None] + name: NotRequired[str | None] + url: str + + +class ProjectSettingsSpanFieldOrderItem(TypedDict): + column_id: str + layout: NotRequired[Literal["full"] | Literal["two_column"] | None] + object_type: str + position: str + + +class ProjectSettings(TypedDict): + baseline_experiment_id: NotRequired[str | None] + """ + The id of the experiment to use as the default baseline for comparisons + """ + comparison_key: NotRequired[str | None] + """ + The key used to join two experiments (defaults to `input`) + """ + default_preprocessor: NotRequired[NullableSavedFunctionId] + disable_realtime_queries: NotRequired[bool | None] + """ + If true, disable real-time queries for this project. This can improve query performance for high-volume logs. + """ + remote_eval_sources: NotRequired[Sequence[ProjectSettingsRemoteEvalSource] | None] + """ + The remote eval sources to use for the project + """ + spanFieldOrder: NotRequired[Sequence[ProjectSettingsSpanFieldOrderItem] | None] + """ + The order of the fields to display in the trace view + """ + + +class ProjectTag(TypedDict): + color: NotRequired[str | None] + """ + Color of the tag for the UI + """ + created: NotRequired[str | None] + """ + Date of project tag creation + """ + description: NotRequired[str | None] + """ + Textual description of the project tag + """ + id: str + """ + Unique identifier for the project tag + """ + name: str + """ + Name of the project tag + """ + position: NotRequired[str | None] + """ + An optional LexoRank-based string that sets the sort position for the tag in the UI + """ + project_id: str + """ + Unique identifier for the project that the project tag belongs under + """ + user_id: str + + +ProjectTagIdParam: TypeAlias = str +""" +ProjectTag id +""" + + +ProjectTagName: TypeAlias = str +""" +Name of the project_tag to search for +""" + + +class PromptBlockDataPromptBlockData1(TypedDict): + content: str + type: Literal["completion"] + + +class PromptBlockDataNullishPromptBlockDataNullish1(TypedDict): + content: str + type: Literal["completion"] + + +class PromptDataMcp(TypedDict): + enabled_tools: NotRequired[Sequence[str] | None] + """ + If omitted, all tools are enabled + """ + id: str + is_disabled: NotRequired[bool] + type: Literal["id"] + + +class PromptDataMcp1(TypedDict): + enabled_tools: NotRequired[Sequence[str] | None] + """ + If omitted, all tools are enabled + """ + is_disabled: NotRequired[bool] + type: Literal["url"] + url: str + + +class PromptDataOrigin(TypedDict): + project_id: NotRequired[str] + prompt_id: NotRequired[str] + prompt_version: NotRequired[str] + + +class ToolFunctionToolFunction(TypedDict): + id: str + type: Literal["function"] + version: NotRequired[str] + """ + The version of the function + """ + + +class ToolFunctionToolFunction1(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + name: str + type: Literal["global"] + + +class ToolFunctionToolFunction2(TypedDict): + pass + + +class ToolFunctionToolFunction3(ToolFunctionToolFunction, ToolFunctionToolFunction2): + pass + + +class ToolFunctionToolFunction4(ToolFunctionToolFunction1, ToolFunctionToolFunction2): + pass + + +class ToolFunctionToolFunction5(ToolFunctionToolFunction, ToolFunctionToolFunction2): + pass + + +class ToolFunctionToolFunction6(ToolFunctionToolFunction1, ToolFunctionToolFunction2): + pass + + +ToolFunction: TypeAlias = ( + ToolFunctionToolFunction3 | ToolFunctionToolFunction4 | ToolFunctionToolFunction5 | ToolFunctionToolFunction6 +) + + +class PromptDataNullishMcp(TypedDict): + enabled_tools: NotRequired[Sequence[str] | None] + """ + If omitted, all tools are enabled + """ + id: str + is_disabled: NotRequired[bool] + type: Literal["id"] + + +class PromptDataNullishMcp1(TypedDict): + enabled_tools: NotRequired[Sequence[str] | None] + """ + If omitted, all tools are enabled + """ + is_disabled: NotRequired[bool] + type: Literal["url"] + url: str + + +class PromptDataNullishOrigin(TypedDict): + project_id: NotRequired[str] + prompt_id: NotRequired[str] + prompt_version: NotRequired[str] + + +class ToolFunction1ToolFunction1(TypedDict): + id: str + type: Literal["function"] + version: NotRequired[str] + """ + The version of the function + """ + + +class ToolFunction1ToolFunction11(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + name: str + type: Literal["global"] + + +class ToolFunction1ToolFunction12(TypedDict): + pass + + +class ToolFunction1ToolFunction13(ToolFunction1ToolFunction1, ToolFunction1ToolFunction12): + pass + + +class ToolFunction1ToolFunction14(ToolFunction1ToolFunction11, ToolFunction1ToolFunction12): + pass + + +class ToolFunction1ToolFunction15(ToolFunction1ToolFunction1, ToolFunction1ToolFunction12): + pass + + +class ToolFunction1ToolFunction16(ToolFunction1ToolFunction11, ToolFunction1ToolFunction12): + pass + + +ToolFunction1: TypeAlias = ( + ToolFunction1ToolFunction13 + | ToolFunction1ToolFunction14 + | ToolFunction1ToolFunction15 + | ToolFunction1ToolFunction16 +) + + +PromptEnvironment: TypeAlias = str +""" +Filter by environment slug. Cannot be used together with `version`. + +For `GET /v1/prompt`, environment resolution currently requires the request to match a single prompt. If multiple prompts match, the endpoint returns `400` (for example when `limit=1` is not set). Use `limit=1` or other filters (for example `slug`, `project_id`) to narrow results. +""" + + +PromptIdParam: TypeAlias = str +""" +Prompt id +""" + + +PromptName: TypeAlias = str +""" +Name of the prompt to search for +""" + + +class PromptParserNullish(TypedDict): + allow_no_match: NotRequired[bool] + """ + If true, adds a 'No match' option. When selected, no tag is deposited. + """ + choice: NotRequired[Sequence[str]] + """ + List of valid choices without score mapping. Used by classifiers that deposit output to tags. + """ + choice_scores: NotRequired[Mapping[str, float]] + """ + Map of choices to scores (0-1). Used by scorers. + """ + type: Literal["llm_classifier"] + use_cot: bool + + +PromptSessionIdParam: TypeAlias = str +""" +PromptSession id +""" + + +PromptSessionName: TypeAlias = str +""" +Name of the prompt_session to search for +""" + + +PromptVersion: TypeAlias = str +""" +Retrieve prompt at a specific version. + +The version id can either be a transaction id (e.g. '1000192656880881099') or a version identifier (e.g. '81cd05ee665fdfb3'). +""" + + +class RepoInfo(TypedDict): + author_email: NotRequired[str | None] + """ + Email of the author of the most recent commit + """ + author_name: NotRequired[str | None] + """ + Name of the author of the most recent commit + """ + branch: NotRequired[str | None] + """ + Name of the branch the most recent commit belongs to + """ + commit: NotRequired[str | None] + """ + SHA of most recent commit + """ + commit_message: NotRequired[str | None] + """ + Most recent commit message + """ + commit_time: NotRequired[str | None] + """ + Time of the most recent commit + """ + dirty: NotRequired[bool | None] + """ + Whether or not the repo had uncommitted changes when snapshotted + """ + git_diff: NotRequired[str | None] + """ + If the repo was dirty when run, this includes the diff between the current state of the repo and the most recent commit. + """ + tag: NotRequired[str | None] + """ + Name of the tag on the most recent commit + """ + + +class ResponseFormatJsonSchema(TypedDict): + description: NotRequired[str] + name: str + schema: NotRequired[Mapping[str, Any] | str] + strict: NotRequired[bool | None] + + +class ResponseFormatNullishResponseFormatNullish(TypedDict): + type: Literal["json_object"] + + +class ResponseFormatNullishResponseFormatNullish1(TypedDict): + json_schema: ResponseFormatJsonSchema + type: Literal["json_schema"] + + +class ResponseFormatNullishResponseFormatNullish2(TypedDict): + type: Literal["text"] + + +ResponseFormatNullish: TypeAlias = ( + ResponseFormatNullishResponseFormatNullish + | ResponseFormatNullishResponseFormatNullish1 + | ResponseFormatNullishResponseFormatNullish2 + | None +) + + +RetentionObjectType: TypeAlias = Literal["project_logs", "experiment", "dataset"] +""" +The object type that the retention policy applies to +""" + + +class RoleMemberPermission(TypedDict): + permission: Permission + restrict_object_type: NotRequired[AclObjectType | None] + + +class Role(TypedDict): + created: NotRequired[str | None] + """ + Date of role creation + """ + deleted_at: NotRequired[str | None] + """ + Date of role deletion, or null if the role is still active + """ + description: NotRequired[str | None] + """ + Textual description of the role + """ + id: str + """ + Unique identifier for the role + """ + member_permissions: NotRequired[Sequence[RoleMemberPermission] | None] + """ + (permission, restrict_object_type) tuples which belong to this role + """ + member_roles: NotRequired[Sequence[str] | None] + """ + Ids of the roles this role inherits from + + An inheriting role has all the permissions contained in its member roles, as well as all of their inherited permissions + """ + name: str + """ + Name of the role + """ + org_id: NotRequired[str | None] + """ + Unique id for the organization that the role belongs under + + A null org_id indicates a system role, which may be assigned to anybody and inherited by any other role, but cannot be edited. + + It is forbidden to change the org after creating a role + """ + user_id: NotRequired[str | None] + """ + Identifies the user who created the role + """ + + +RoleIdParam: TypeAlias = str +""" +Role id +""" + + +RoleName: TypeAlias = str +""" +Name of the role to search for +""" + + +class RunEvalData(TypedDict): + field_internal_btql: NotRequired[Mapping[str, Any] | None] + dataset_environment: NotRequired[str | None] + """ + The environment tag that resolves to the dataset version to evaluate + """ + dataset_id: str + dataset_version: NotRequired[str | None] + """ + The version of the dataset to evaluate + """ + + +class RunEvalData1(TypedDict): + field_internal_btql: NotRequired[Mapping[str, Any] | None] + dataset_environment: NotRequired[str | None] + """ + The environment tag that resolves to the dataset version to evaluate + """ + dataset_name: str + dataset_version: NotRequired[str | None] + """ + The version of the dataset to evaluate + """ + project_name: str + + +class RunEvalData2(TypedDict): + data: Sequence[Any] + + +class RunEvalMcpAuth(TypedDict): + oauth_token: NotRequired[str] + """ + The OAuth token to use + """ + + +class ParentParentRowIds(TypedDict): + id: str + """ + The id of the row + """ + root_span_id: str + """ + The root_span_id of the row + """ + span_id: str + """ + The span_id of the row + """ + + +class ParentParent(TypedDict): + object_id: str + """ + The id of the container object you are logging to + """ + object_type: Literal["project_logs", "experiment", "playground_logs"] + propagated_event: NotRequired[Mapping[str, Any] | None] + """ + Include these properties in every span created under this parent + """ + row_ids: NotRequired[ParentParentRowIds | None] + """ + Identifiers for the row to to log a subspan under + """ + + +class ParentParent1(TypedDict): + pass + + +class ParentParent2(ParentParent, ParentParent1): + pass + + +Parent: TypeAlias = ParentParent2 + + +class ScoreScore(TypedDict): + function_id: str + """ + The ID of the function + """ + version: NotRequired[str] + """ + The version of the function + """ + + +class ScoreScore1(TypedDict): + project_name: str + """ + The name of the project containing the function + """ + slug: str + """ + The slug of the function + """ + version: NotRequired[str] + """ + The version of the function + """ + + +class ScoreScore2(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + global_function: str + """ + The name of the global function. Currently, the global namespace includes the functions in autoevals + """ + + +class ScoreScore3(TypedDict): + prompt_session_function_id: str + """ + The ID of the function in the prompt session + """ + prompt_session_id: str + """ + The ID of the prompt session + """ + version: NotRequired[str] + """ + The version of the function + """ + + +class ScoreScore4InlineContext(TypedDict): + runtime: Literal["node", "python", "browser", "quickjs"] + version: str + + +class ScoreScore4(TypedDict): + code: str + """ + The inline code to execute + """ + function_type: NotRequired[FunctionTypeEnum] + inline_context: ScoreScore4InlineContext + name: NotRequired[str | None] + """ + The name of the inline code function + """ + + +class ScoreScore7(TypedDict): + pass + + +class ScoreScore8(ScoreScore, ScoreScore7): + pass + + +class ScoreScore9(ScoreScore1, ScoreScore7): + pass + + +class ScoreScore10(ScoreScore2, ScoreScore7): + pass + + +class ScoreScore11(ScoreScore3, ScoreScore7): + pass + + +class ScoreScore12(ScoreScore4, ScoreScore7): + pass + + +class SavedFunctionIdSavedFunctionId(TypedDict): + id: str + type: Literal["function"] + version: NotRequired[str] + """ + The version of the function + """ + + +class SavedFunctionIdSavedFunctionId1(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + name: str + type: Literal["global"] + + +SavedFunctionId: TypeAlias = SavedFunctionIdSavedFunctionId | SavedFunctionIdSavedFunctionId1 | None +""" +Optional function identifier that produced the classification +""" + + +class ScoreSummary(TypedDict): + diff: NotRequired[float] + """ + Difference in score between the current and comparison experiment + """ + improvements: int + """ + Number of improvements in the score + """ + name: str + """ + Name of the score + """ + regressions: int + """ + Number of regressions in the score + """ + score: float + """ + Average score across all examples + """ + + +class ServiceToken(TypedDict): + created: NotRequired[str | None] + """ + Date of service token creation + """ + id: str + """ + Unique identifier for the service token + """ + name: str + """ + Name of the service token + """ + org_id: NotRequired[str | None] + """ + Unique identifier for the organization + """ + preview_name: str + service_account_email: NotRequired[str | None] + """ + The service account email (not routable) + """ + service_account_id: NotRequired[str | None] + """ + Unique identifier for the service token + """ + service_account_name: NotRequired[str | None] + """ + The service account name + """ + + +ServiceTokenIdParam: TypeAlias = str +""" +ServiceToken id +""" + + +ServiceTokenName: TypeAlias = str +""" +Name of the service_token to search for +""" + + +Slug: TypeAlias = str +""" +Retrieve prompt with a specific slug +""" + + +class SpanIFrame(TypedDict): + created: NotRequired[str | None] + """ + Date of span iframe creation + """ + deleted_at: NotRequired[str | None] + """ + Date of span iframe deletion, or null if the span iframe is still active + """ + description: NotRequired[str | None] + """ + Textual description of the span iframe + """ + id: str + """ + Unique identifier for the span iframe + """ + name: str + """ + Name of the span iframe + """ + post_message: NotRequired[bool | None] + """ + Whether to post messages to the iframe containing the span's data. This is useful when you want to render more data than fits in the URL. + """ + project_id: str + """ + Unique identifier for the project that the span iframe belongs under + """ + url: str + """ + URL to embed the project viewer in an iframe + """ + user_id: NotRequired[str | None] + """ + Identifies the user who created the span iframe + """ + + +SpanIframeIdParam: TypeAlias = str +""" +SpanIframe id +""" + + +SpanIframeName: TypeAlias = str +""" +Name of the span_iframe to search for +""" + + +class SpanScope(TypedDict): + type: Literal["span"] + + +SpanType: TypeAlias = ( + Literal[ + "llm", + "score", + "function", + "eval", + "task", + "tool", + "automation", + "facet", + "preprocessor", + "classifier", + "review", + ] + | None +) +""" +Type of the span, for display purposes only +""" + + +StartingAfter: TypeAlias = str +""" +Pagination cursor id. + +For example, if the final item in the last page you fetched had an id of `foo`, pass `starting_after=foo` to fetch the next page. Note: you may only pass one of `starting_after` and `ending_before` +""" + + +StreamingMode: TypeAlias = Literal["auto", "parallel", "json", "text"] | None +""" +The mode format of the returned value (defaults to 'auto') +""" + + +SummarizeData: TypeAlias = bool | None +""" +Whether to summarize the data. If false (or omitted), only the metadata will be returned. +""" + + +class SummarizeDatasetResponse(TypedDict): + data_summary: NotRequired[DataSummary | None] + dataset_name: str + """ + Name of the dataset + """ + dataset_url: str + """ + URL to the dataset's page in the Braintrust app + """ + project_name: str + """ + Name of the project that the dataset belongs to + """ + project_url: str + """ + URL to the project's page in the Braintrust app + """ + + +class SummarizeExperimentResponse(TypedDict): + comparison_experiment_name: NotRequired[str | None] + """ + The experiment which scores are baselined against + """ + experiment_name: str + """ + Name of the experiment + """ + experiment_url: str + """ + URL to the experiment's page in the Braintrust app + """ + metrics: NotRequired[Mapping[str, MetricSummary] | None] + """ + Summary of the experiment's metrics + """ + project_name: str + """ + Name of the project that the experiment belongs to + """ + project_url: str + """ + URL to the project's page in the Braintrust app + """ + scores: NotRequired[Mapping[str, ScoreSummary] | None] + """ + Summary of the experiment's scores + """ + + +SummarizeScores: TypeAlias = bool | None +""" +Whether to summarize the scores and metrics. If false (or omitted), only the metadata will be returned. +""" + + +TopicAutomationConfigBackfillTimeRange = TypedDict( + "TopicAutomationConfigBackfillTimeRange", + { + "from": str, + "to": str, + }, +) + + +class FacetFunctionFacetFunction(TypedDict): + id: str + type: Literal["function"] + version: NotRequired[str] + """ + The version of the function + """ + + +class FacetFunctionFacetFunction1(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + name: str + type: Literal["global"] + + +class FacetFunctionFacetFunction2(TypedDict): + pass + + +class FacetFunctionFacetFunction3(FacetFunctionFacetFunction, FacetFunctionFacetFunction2): + pass + + +class FacetFunctionFacetFunction4(FacetFunctionFacetFunction1, FacetFunctionFacetFunction2): + pass + + +class FacetFunctionFacetFunction5(FacetFunctionFacetFunction, FacetFunctionFacetFunction2): + pass + + +class FacetFunctionFacetFunction6(FacetFunctionFacetFunction1, FacetFunctionFacetFunction2): + pass + + +FacetFunction: TypeAlias = ( + FacetFunctionFacetFunction3 + | FacetFunctionFacetFunction4 + | FacetFunctionFacetFunction5 + | FacetFunctionFacetFunction6 +) + + +class TopicAutomationDataScopeTopicAutomationDataScope(TypedDict): + type: Literal["project_logs"] + + +class TopicAutomationDataScopeTopicAutomationDataScope1(TypedDict): + type: Literal["project_experiments"] + + +class TopicAutomationDataScopeTopicAutomationDataScope2(TypedDict): + experiment_id: str + type: Literal["experiment"] + + +TopicAutomationDataScope: TypeAlias = ( + TopicAutomationDataScopeTopicAutomationDataScope + | TopicAutomationDataScopeTopicAutomationDataScope1 + | TopicAutomationDataScopeTopicAutomationDataScope2 + | None +) +""" +Optional data scope for topic automation. +""" + + +TopicAutomationFacetModel: TypeAlias = Literal["brain-facet-latest", "brain-facet-1", "brain-facet-2"] | None +""" +Optional facet model override for topic automation +""" + + +class TopicDigestAutomationConfigAction(TypedDict): + channel: str + """ + The Slack channel ID to post to + """ + message_template: NotRequired[str] + """ + Custom message template for the alert + """ + type: Literal["slack"] + """ + The type of action to take + """ + workspace_id: str + """ + The Slack workspace ID to post to + """ + + +class TopicDigestAutomationConfig(TypedDict): + action: TopicDigestAutomationConfigAction + """ + The Slack action to take when the digest is sent + """ + event_type: Literal["topic_digest"] + """ + The type of automation. + """ + scheduled_time_minutes_utc: int + """ + Minutes after midnight UTC when the digest should be sent + """ + status: NotRequired[AutomationStatus] + topic_map_function_ids: NotRequired[Sequence[str]] + """ + Optional topic map function IDs to include in the digest + """ + window_seconds: NotRequired[int] + """ + How much recent history to include in each digest + """ + + +class Function1Function1(TypedDict): + id: str + type: Literal["function"] + version: NotRequired[str] + """ + The version of the function + """ + + +class Function1Function11(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + name: str + type: Literal["global"] + + +class Function1Function12(TypedDict): + pass + + +class Function1Function13(Function1Function1, Function1Function12): + pass + + +class Function1Function14(Function1Function11, Function1Function12): + pass + + +class Function1Function15(Function1Function1, Function1Function12): + pass + + +class Function1Function16(Function1Function11, Function1Function12): + pass + + +Function1: TypeAlias = Function1Function13 | Function1Function14 | Function1Function15 | Function1Function16 + + +class TopicMapFunctionAutomation(TypedDict): + btql_filter: NotRequired[str | None] + """ + Per-topic-map BTQL filter. For trace scope, a topic map runs when max(filter) over the trace is truthy. For span scope, it runs when the current span matches. + """ + function: Function1 + + +class TopicMapGenerationSettings(TypedDict): + algorithm: Literal["hdbscan", "kmeans"] + dimension_reduction: Literal["umap", "pca", "none"] + hierarchy_threshold: NotRequired[int] + min_cluster_size: NotRequired[int] + min_samples: NotRequired[int] + n_clusters: NotRequired[int] + naming_model: NotRequired[str] + sample_size: NotRequired[int] + + +class TraceScope(TypedDict): + idle_seconds: NotRequired[float] + """ + Consider trace complete after this many seconds of inactivity (default: 30) + """ + type: Literal["trace"] + + +class User(TypedDict): + avatar_url: NotRequired[str | None] + """ + URL of the user's Avatar image + """ + created: NotRequired[str | None] + """ + Date of user creation + """ + email: NotRequired[str | None] + """ + The user's email + """ + family_name: NotRequired[str | None] + """ + Family name of the user + """ + given_name: NotRequired[str | None] + """ + Given name of the user + """ + id: str + """ + Unique identifier for the user + """ + + +UserEmail: TypeAlias = str | Sequence[str] +""" +Email of the user to search for. You may pass the param multiple times to filter for more than one email +""" + + +UserFamilyName: TypeAlias = str | Sequence[str] +""" +Family name of the user to search for. You may pass the param multiple times to filter for more than one family name +""" + + +UserGivenName: TypeAlias = str | Sequence[str] +""" +Given name of the user to search for. You may pass the param multiple times to filter for more than one given name +""" + + +UserIdParam: TypeAlias = str +""" +User id +""" + + +Version: TypeAlias = str +""" +Retrieve a snapshot of events from a past time + +The version id is essentially a filter on the latest event transaction id. You can use the `max_xact_id` returned by a past fetch as the version to reproduce that exact fetch. +""" + + +class ViewDataSearch(TypedDict): + filter: NotRequired[Sequence[Any] | None] + match: NotRequired[Sequence[Any] | None] + sort: NotRequired[Sequence[Any] | None] + tag: NotRequired[Sequence[Any] | None] + + +ViewIdParam: TypeAlias = str +""" +View id +""" + + +ViewName: TypeAlias = str +""" +Name of the view to search for +""" + + +class ViewOptionsViewOptionsOptions(TypedDict): + chartVisibility: NotRequired[Mapping[str, bool] | None] + frameEnd: NotRequired[str | None] + frameStart: NotRequired[str | None] + groupBy: NotRequired[str | None] + projectId: NotRequired[str | None] + rangeValue: NotRequired[str | None] + spanType: NotRequired[Literal["range", "frame"] | None] + type: NotRequired[Literal["project", "experiment"] | None] + tzUTC: NotRequired[bool | None] + + +class ViewOptionsViewOptions(TypedDict): + freezeColumns: NotRequired[bool | None] + options: ViewOptionsViewOptionsOptions + viewType: Literal["monitor"] + + +class ViewOptionsViewOptions1ChartAnnotation(TypedDict): + id: str + text: str + + +class ViewOptionsViewOptions1ExcludedMeasure(TypedDict): + type: Literal["none", "score", "metric", "metadata"] + value: str + + +class ViewOptionsViewOptions1SymbolGrouping(TypedDict): + type: Literal["none", "score", "metric", "metadata"] + value: str + + +ViewOptionsViewOptions1TimeRangeFilter = TypedDict( + "ViewOptionsViewOptions1TimeRangeFilter", + { + "from": str, + "to": str, + }, +) + + +class ViewOptionsViewOptions1XAxis(TypedDict): + type: Literal["none", "score", "metric", "metadata"] + value: str + + +class ViewOptionsViewOptions1YMetric(TypedDict): + type: Literal["none", "score", "metric", "metadata"] + value: str + + +class ViewOptionsViewOptions1(TypedDict): + chartAnnotations: NotRequired[Sequence[ViewOptionsViewOptions1ChartAnnotation] | None] + chartHeight: NotRequired[float | None] + cluster: NotRequired[str | None] + columnOrder: NotRequired[Sequence[str] | None] + columnSizing: NotRequired[Mapping[str, float] | None] + columnVisibility: NotRequired[Mapping[str, bool] | None] + excludedMeasures: NotRequired[Sequence[ViewOptionsViewOptions1ExcludedMeasure] | None] + freezeColumns: NotRequired[bool | None] + grouping: NotRequired[str | None] + layout: NotRequired[str | None] + queryShape: NotRequired[Literal["traces", "spans", "topics"] | None] + rowHeight: NotRequired[str | None] + symbolGrouping: NotRequired[ViewOptionsViewOptions1SymbolGrouping | None] + tallGroupRows: NotRequired[bool | None] + timeRangeFilter: NotRequired[str | ViewOptionsViewOptions1TimeRangeFilter | None] + topicMapReportKey: NotRequired[str | None] + xAxis: NotRequired[ViewOptionsViewOptions1XAxis | None] + xAxisAggregation: NotRequired[str | None] + """ + One of 'avg', 'sum', 'min', 'max', 'median', 'all' + """ + yMetric: NotRequired[ViewOptionsViewOptions1YMetric | None] + + +ViewOptions: TypeAlias = ViewOptionsViewOptions | ViewOptionsViewOptions1 | None +""" +Options for the view in the app +""" + + +ViewType: TypeAlias = ( + Literal[ + "projects", + "experiments", + "experiment", + "playgrounds", + "playground", + "datasets", + "dataset", + "prompts", + "parameters", + "tools", + "scorers", + "classifiers", + "logs", + "monitor", + "for_review_project_log", + "for_review_experiments", + "for_review_datasets", + ] + | None +) +""" +Type of object that the view corresponds to. +""" + + +class Acl(TypedDict): + field_object_org_id: str + """ + The organization the ACL's referred object belongs to + """ + created: NotRequired[str | None] + """ + Date of acl creation + """ + group_id: NotRequired[str | None] + """ + Id of the group the ACL applies to. Exactly one of `user_id` and `group_id` will be provided + """ + id: str + """ + Unique identifier for the acl + """ + object_id: str + """ + The id of the object the ACL applies to + """ + object_type: AclObjectType + permission: NotRequired[Permission | None] + """ + Permission the ACL grants. Exactly one of `permission` and `role_id` will be provided + """ + restrict_object_type: NotRequired[AclObjectType | None] + """ + When setting a permission directly, optionally restricts the permission grant to just the specified object type. Cannot be set alongside a `role_id`. + """ + role_id: NotRequired[str | None] + """ + Id of the role the ACL grants. Exactly one of `permission` and `role_id` will be provided + """ + user_id: NotRequired[str | None] + """ + Id of the user the ACL applies to. Exactly one of `user_id` and `group_id` will be provided + """ + + +class AclBatchUpdateResponse(TypedDict): + added_acls: Sequence[Acl] + removed_acls: Sequence[Acl] + + +class AclItem(TypedDict): + group_id: NotRequired[str | None] + """ + Id of the group the ACL applies to. Exactly one of `user_id` and `group_id` will be provided + """ + object_id: str + """ + The id of the object the ACL applies to + """ + object_type: AclObjectType + permission: NotRequired[Permission | None] + """ + Permission the ACL grants. Exactly one of `permission` and `role_id` will be provided + """ + restrict_object_type: NotRequired[AclObjectType | None] + """ + When setting a permission directly, optionally restricts the permission grant to just the specified object type. Cannot be set alongside a `role_id`. + """ + role_id: NotRequired[str | None] + """ + Id of the role the ACL grants. Exactly one of `permission` and `role_id` will be provided + """ + user_id: NotRequired[str | None] + """ + Id of the user the ACL applies to. Exactly one of `user_id` and `group_id` will be provided + """ + + +class PreprocessorPreprocessor1(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + name: str + type: Literal["global"] + + +class PreprocessorPreprocessor4(PreprocessorPreprocessor1, PreprocessorPreprocessor2): + pass + + +Preprocessor: TypeAlias = PreprocessorPreprocessor3 | PreprocessorPreprocessor4 + + +ChatCompletionContentPart: TypeAlias = ( + ChatCompletionContentPartTextWithTitle + | ChatCompletionContentPartImageWithTitle + | ChatCompletionContentPartFileWithTitle +) + + +class ChatCompletionMessageParamChatCompletionMessageParam1(TypedDict): + content: NotRequired[str | Sequence[ChatCompletionContentPart]] + name: NotRequired[str] + role: Literal["user"] + + +class ChatCompletionMessageParamChatCompletionMessageParam2(TypedDict): + content: NotRequired[str | Sequence[ChatCompletionContentPartText] | None] + function_call: NotRequired[ChatCompletionMessageParamChatCompletionMessageParam2FunctionCall | None] + name: NotRequired[str | None] + reasoning: NotRequired[Sequence[ChatCompletionMessageReasoning] | None] + reasoning_signature: NotRequired[str | None] + role: Literal["assistant"] + tool_calls: NotRequired[Sequence[ChatCompletionMessageToolCall] | None] + + +ChatCompletionMessageParam: TypeAlias = ( + ChatCompletionMessageParamChatCompletionMessageParam + | ChatCompletionMessageParamChatCompletionMessageParam1 + | ChatCompletionMessageParamChatCompletionMessageParam2 + | ChatCompletionMessageParamChatCompletionMessageParam3 + | ChatCompletionMessageParamChatCompletionMessageParam4 + | ChatCompletionMessageParamChatCompletionMessageParam5 + | ChatCompletionMessageParamChatCompletionMessageParam6 +) + + +class CreateExperiment(TypedDict): + base_exp_id: NotRequired[str | None] + """ + Id of default base experiment to compare against when viewing this experiment + """ + dataset_id: NotRequired[str | None] + """ + Identifier of the linked dataset, or null if the experiment is not linked to a dataset + """ + dataset_version: NotRequired[str | None] + """ + Version number of the linked dataset the experiment was run against. This can be used to reproduce the experiment after the dataset has been modified. + """ + description: NotRequired[str | None] + """ + Textual description of the experiment + """ + ensure_new: NotRequired[bool | None] + """ + Normally, creating an experiment with the same name as an existing experiment will return the existing one un-modified. But if `ensure_new` is true, registration will generate a new experiment with a unique name in case of a conflict. + """ + internal_metadata: NotRequired[CreateExperimentInternalMetadata | None] + """ + Braintrust-controlled metadata about the experiment. + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + User-controlled metadata about the experiment + """ + name: NotRequired[str | None] + """ + Name of the experiment. Within a project, experiment names are unique + """ + parameters_id: NotRequired[str | None] + """ + Identifier of the linked saved parameters object, or null if the experiment is not linked to saved parameters + """ + parameters_version: NotRequired[str | None] + """ + Version number of the linked saved parameters object the experiment was run against. + """ + project_id: str + """ + Unique identifier for the project that the experiment belongs under + """ + public: NotRequired[bool | None] + """ + Whether or not the experiment is public. Public experiments can be viewed by anybody inside or outside the organization + """ + repo_info: NotRequired[RepoInfo | None] + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the experiment + """ + + +class CreateProjectAutomationConfig1(TypedDict): + batch_size: NotRequired[float | None] + """ + The number of rows to export in each batch + """ + credentials: CreateProjectAutomationConfig1Credentials | CreateProjectAutomationConfig1Credentials1 + event_type: Literal["btql_export"] + """ + The type of automation. + """ + export_definition: ( + CreateProjectAutomationConfig1ExportDefinition + | CreateProjectAutomationConfig1ExportDefinition1 + | CreateProjectAutomationConfig1ExportDefinition2 + ) + """ + The definition of what to export + """ + export_path: str + """ + The path to export the results to. It should include the storage protocol and prefix, e.g. s3://bucket-name/path/to/export + """ + format: Literal["jsonl", "parquet"] + """ + The format to export the results in + """ + interval_seconds: float + """ + Perform the triggered action at most once in this interval of seconds + """ + scope: NotRequired[SpanScope | TraceScope | GroupScope | None] + """ + Execution scope for export automation. Defaults to span-level execution. + """ + status: NotRequired[AutomationStatus] + + +class CreateProjectAutomationConfig3(TypedDict): + event_type: Literal["retention"] + """ + The type of automation. + """ + object_type: RetentionObjectType + retention_days: float + """ + The number of days to retain the object + """ + + +class CreateRoleMemberPermission(TypedDict): + permission: Permission + restrict_object_type: NotRequired[AclObjectType | None] + + +class CreateRole(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the role + """ + member_permissions: NotRequired[Sequence[CreateRoleMemberPermission] | None] + """ + (permission, restrict_object_type) tuples which belong to this role + """ + member_roles: NotRequired[Sequence[str] | None] + """ + Ids of the roles this role inherits from + + An inheriting role has all the permissions contained in its member roles, as well as all of their inherited permissions + """ + name: str + """ + Name of the role + """ + org_name: NotRequired[str | None] + """ + For nearly all users, this parameter should be unnecessary. But in the rare case that your API key belongs to multiple organizations, you may specify the name of the organization the role belongs in. + """ + + +class CrossObjectInsertResponse(TypedDict): + dataset: NotRequired[Mapping[str, InsertEventsResponse] | None] + """ + A mapping from dataset id to row ids for inserted `events` + """ + experiment: NotRequired[Mapping[str, InsertEventsResponse] | None] + """ + A mapping from experiment id to row ids for inserted `events` + """ + project_logs: NotRequired[Mapping[str, InsertEventsResponse] | None] + """ + A mapping from project id to row ids for inserted `events` + """ + + +class DatasetEventClassification(TypedDict): + confidence: NotRequired[float | None] + """ + Optional confidence score for the classification + """ + id: str + """ + Stable classification identifier + """ + label: NotRequired[str] + """ + Original label of the classification item, which is useful for search and indexing purposes + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + Optional metadata associated with the classification + """ + source: NotRequired[SavedFunctionId] + + +class DatasetEvent(TypedDict): + field_pagination_key: NotRequired[str | None] + """ + A stable, time-ordered key that can be used to paginate over dataset events. This field is auto-generated by Braintrust and only exists in Brainstore. + """ + field_xact_id: str + """ + The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the dataset (see the `version` parameter) + """ + audit_data: NotRequired[Sequence[Any] | None] + """ + Optional list of audit entries attached to this event + """ + classifications: NotRequired[Mapping[str, Sequence[DatasetEventClassification]] | None] + """ + Classifications for this event (dictionary from classification name to items) + """ + comments: NotRequired[Sequence[Any] | None] + """ + Optional list of comments attached to this event + """ + created: str + """ + The timestamp the dataset event was created + """ + dataset_id: str + """ + Unique identifier for the dataset + """ + expected: NotRequired[Any | None] + """ + The output of your application, including post-processing (an arbitrary, JSON serializable object) + """ + facets: NotRequired[Mapping[str, str | None] | None] + """ + Facets for categorization (dictionary from facet id to value) + """ + id: str + """ + A unique identifier for the dataset event. If you don't provide one, Braintrust will generate one for you + """ + input: NotRequired[Any | None] + """ + The argument that uniquely define an input case (an arbitrary, JSON serializable object) + """ + is_root: NotRequired[bool | None] + """ + Whether this span is a root span + """ + metadata: NotRequired[DatasetEventMetadata | None] + """ + A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings + """ + origin: NotRequired[ObjectReferenceNullish | None] + project_id: str + """ + Unique identifier for the project that the dataset belongs under + """ + root_span_id: str + """ + A unique identifier for the trace this dataset event belongs to + """ + span_id: str + """ + A unique identifier used to link different dataset events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags to log + """ + + +class Experiment(TypedDict): + base_exp_id: NotRequired[str | None] + """ + Id of default base experiment to compare against when viewing this experiment + """ + commit: NotRequired[str | None] + """ + Commit, taken directly from `repo_info.commit` + """ + created: NotRequired[str | None] + """ + Date of experiment creation + """ + dataset_id: NotRequired[str | None] + """ + Identifier of the linked dataset, or null if the experiment is not linked to a dataset + """ + dataset_version: NotRequired[str | None] + """ + Version number of the linked dataset the experiment was run against. This can be used to reproduce the experiment after the dataset has been modified. + """ + deleted_at: NotRequired[str | None] + """ + Date of experiment deletion, or null if the experiment is still active + """ + description: NotRequired[str | None] + """ + Textual description of the experiment + """ + id: str + """ + Unique identifier for the experiment + """ + internal_metadata: NotRequired[ExperimentInternalMetadata | None] + """ + Braintrust-controlled metadata about the experiment. + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + User-controlled metadata about the experiment + """ + name: str + """ + Name of the experiment. Within a project, experiment names are unique + """ + parameters_id: NotRequired[str | None] + """ + Identifier of the linked saved parameters object, or null if the experiment is not linked to saved parameters + """ + parameters_version: NotRequired[str | None] + """ + Version number of the linked saved parameters object the experiment was run against. + """ + project_id: str + """ + Unique identifier for the project that the experiment belongs under + """ + public: bool + """ + Whether or not the experiment is public. Public experiments can be viewed by anybody inside or outside the organization + """ + repo_info: NotRequired[RepoInfo | None] + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the experiment + """ + user_id: NotRequired[str | None] + """ + Identifies the user who created the experiment + """ + + +class ExperimentEventClassification(TypedDict): + confidence: NotRequired[float | None] + """ + Optional confidence score for the classification + """ + id: str + """ + Stable classification identifier + """ + label: NotRequired[str] + """ + Original label of the classification item, which is useful for search and indexing purposes + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + Optional metadata associated with the classification + """ + source: NotRequired[SavedFunctionId] + + +class Preprocessor1Preprocessor11(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + name: str + type: Literal["global"] + + +class Preprocessor1Preprocessor14(Preprocessor1Preprocessor11, Preprocessor1Preprocessor12): + pass + + +Preprocessor1: TypeAlias = Preprocessor1Preprocessor13 | Preprocessor1Preprocessor14 + + +class FacetData(TypedDict): + embedding_model: NotRequired[str] + """ + The embedding model to use for vectorizing facet results. + """ + model: NotRequired[str] + """ + The model to use for facet extraction + """ + no_match_pattern: NotRequired[str] + """ + Regex pattern to identify outputs that do not match the facet. If the output matches, the facet will be saved as 'no_match' + """ + preprocessor: NotRequired[Preprocessor1] + prompt: str + """ + The prompt to use for LLM extraction. The preprocessed text will be provided as context. + """ + type: Literal["facet"] + + +class FeedbackDatasetEventRequest(TypedDict): + feedback: Sequence[FeedbackDatasetItem] + """ + A list of dataset feedback items + """ + + +class FeedbackExperimentEventRequest(TypedDict): + feedback: Sequence[FeedbackExperimentItem] + """ + A list of experiment feedback items + """ + + +class FeedbackProjectLogsEventRequest(TypedDict): + feedback: Sequence[FeedbackProjectLogsItem] + """ + A list of project logs feedback items + """ + + +class FetchDatasetEventsResponse(TypedDict): + cursor: NotRequired[str | None] + """ + Pagination cursor + + Pass this string directly as the `cursor` param to your next fetch request to get the next page of results. Not provided if the returned result set is empty. + """ + events: Sequence[DatasetEvent] + """ + A list of fetched events + """ + + +class FetchEventsRequest(TypedDict): + cursor: NotRequired[FetchPaginationCursor | None] + limit: NotRequired[FetchLimit | None] + max_root_span_id: NotRequired[MaxRootSpanId | None] + max_xact_id: NotRequired[MaxXactId | None] + version: NotRequired[Version | None] + + +class FunctionDataFunctionData3(TypedDict): + config: NotRequired[Mapping[str, Any] | None] + """ + Configuration options to pass to the global function (e.g., for preprocessor customization) + """ + function_type: NotRequired[FunctionTypeEnum] + name: str + type: Literal["global"] + + +class FunctionDataNullishFunctionDataNullish3(TypedDict): + config: NotRequired[Mapping[str, Any] | None] + """ + Configuration options to pass to the global function (e.g., for preprocessor customization) + """ + function_type: NotRequired[FunctionTypeEnum] + name: str + type: Literal["global"] + + +class FunctionIdFunctionId2(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + global_function: str + """ + The name of the global function. Currently, the global namespace includes the functions in autoevals + """ + + +class FunctionIdFunctionId4(TypedDict): + code: str + """ + The inline code to execute + """ + function_type: NotRequired[FunctionTypeEnum] + inline_context: FunctionIdFunctionId4InlineContext + name: NotRequired[str | None] + """ + The name of the inline code function + """ + + +class InsertDatasetEvent(TypedDict): + field_array_delete: NotRequired[Sequence[InsertDatasetEventFieldArrayDeleteItem] | None] + """ + The `_array_delete` field allows removing specific values from array fields. It is an array of objects with `path` and `delete` properties. + + For example, to remove tags "foo" and "bar" from an existing row: `{"_is_merge": true, "_array_delete": [{"path": ["tags"], "delete": ["foo", "bar"]}]}`. For nested fields like `metadata.categories`, use `[{"path": ["metadata", "categories"], "delete": ["value"]}]`. This will remove those specific values from the array while preserving others. + """ + field_is_merge: NotRequired[bool | None] + """ + The `_is_merge` field controls how the row is merged with any existing row with the same id in the DB. By default (or when set to `false`), the existing row is completely replaced by the new row. When set to `true`, the new row is deep-merged into the existing row, if one is found. If no existing row is found, the new row is inserted as is. + + For example, say there is an existing row in the DB `{"id": "foo", "input": {"a": 5, "b": 10}}`. If we merge a new row as `{"_is_merge": true, "id": "foo", "input": {"b": 11, "c": 20}}`, the new row will be `{"id": "foo", "input": {"a": 5, "b": 11, "c": 20}}`. If we replace the new row as `{"id": "foo", "input": {"b": 11, "c": 20}}`, the new row will be `{"id": "foo", "input": {"b": 11, "c": 20}}` + """ + field_merge_paths: NotRequired[Sequence[Sequence[str]] | None] + """ + The `_merge_paths` field allows controlling the depth of the merge, when `_is_merge=true`. `_merge_paths` is a list of paths, where each path is a list of field names. The deep merge will not descend below any of the specified merge paths. + + For example, say there is an existing row in the DB `{"id": "foo", "input": {"a": {"b": 10}, "c": {"d": 20}}, "output": {"a": 20}}`. If we merge a new row as `{"_is_merge": true, "_merge_paths": [["input", "a"], ["output"]], "input": {"a": {"q": 30}, "c": {"e": 30}, "bar": "baz"}, "output": {"d": 40}}`, the new row will be `{"id": "foo": "input": {"a": {"q": 30}, "c": {"d": 20, "e": 30}, "bar": "baz"}, "output": {"d": 40}}`. In this case, due to the merge paths, we have replaced `input.a` and `output`, but have still deep-merged `input` and `input.c`. + """ + field_object_delete: NotRequired[bool | None] + """ + Pass `_object_delete=true` to mark the dataset event deleted. Deleted events will not show up in subsequent fetches for this dataset + """ + field_parent_id: NotRequired[str | None] + """ + DEPRECATED: The `_parent_id` field is deprecated and should not be used. Support for `_parent_id` will be dropped in a future version of Braintrust. Log `span_id`, `root_span_id`, and `span_parents` explicitly instead. + + Use the `_parent_id` field to create this row as a subspan of an existing row. Tracking hierarchical relationships are important for tracing (see the [guide](https://www.braintrust.dev/docs/instrument) for full details). + + For example, say we have logged a row `{"id": "abc", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"_parent_id": "abc", "id": "llm_call", "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + created: NotRequired[str | None] + """ + The timestamp the dataset event was created + """ + expected: NotRequired[Any | None] + """ + The output of your application, including post-processing (an arbitrary, JSON serializable object) + """ + facets: NotRequired[Mapping[str, str | None] | None] + """ + Facets for categorization (dictionary from facet id to value) + """ + id: NotRequired[str | None] + """ + A unique identifier for the dataset event. If you don't provide one, Braintrust will generate one for you + """ + input: NotRequired[Any | None] + """ + The argument that uniquely define an input case (an arbitrary, JSON serializable object) + """ + metadata: NotRequired[InsertDatasetEventMetadata | None] + """ + A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings + """ + origin: NotRequired[ObjectReferenceNullish | None] + root_span_id: NotRequired[str | None] + """ + Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details. + + For example, say we have logged a row `{"id": "abc", "span_id": "span0", "root_span_id": "root_span0", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"id": "llm_call", "span_id": "span1", "root_span_id": "root_span0", "span_parents": ["span0"], "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + span_id: NotRequired[str | None] + """ + Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details. + + For example, say we have logged a row `{"id": "abc", "span_id": "span0", "root_span_id": "root_span0", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"id": "llm_call", "span_id": "span1", "root_span_id": "root_span0", "span_parents": ["span0"], "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + span_parents: NotRequired[Sequence[str] | None] + """ + Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details. + + For example, say we have logged a row `{"id": "abc", "span_id": "span0", "root_span_id": "root_span0", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"id": "llm_call", "span_id": "span1", "root_span_id": "root_span0", "span_parents": ["span0"], "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags to log + """ + + +class InsertDatasetEventRequest(TypedDict): + events: Sequence[InsertDatasetEvent] + """ + A list of dataset events to insert + """ + + +class InvokeApi(TypedDict): + expected: NotRequired[Any | None] + """ + The expected output of the function + """ + input: NotRequired[Any | None] + """ + Argument to the function, which can be any JSON serializable value + """ + mcp_auth: NotRequired[Mapping[str, InvokeApiMcpAuth]] + """ + Map of MCP server URL to auth credentials + """ + messages: NotRequired[Sequence[ChatCompletionMessageParam]] + """ + If the function is an LLM, additional messages to pass along to it + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + Any relevant metadata. This will be logged and available as the `metadata` argument. + """ + mode: NotRequired[StreamingMode | None] + overrides: NotRequired[Mapping[str, Any] | None] + """ + Partial function definition to merge with the function being invoked. Fields are validated against the function type's schema at runtime. For facets: { preprocessor?, prompt?, model? }. For prompts: { model?, ... }. + """ + parent: NotRequired[InvokeParent] + stream: NotRequired[bool | None] + """ + Whether to stream the response. If true, results will be returned in the Braintrust SSE format. + """ + strict: NotRequired[bool | None] + """ + If true, throw an error if one of the variables in the prompt is not present in the input + """ + tags: NotRequired[Sequence[str] | None] + """ + Any relevant tags to log on the span. + """ + version: NotRequired[str] + """ + The version of the function + """ + + +class ModelParamsModelParams(TypedDict): + frequency_penalty: NotRequired[float] + function_call: NotRequired[Literal["auto"] | Literal["none"] | ModelParamsModelParamsFunctionCall] + max_completion_tokens: NotRequired[float] + """ + The successor to max_tokens + """ + max_tokens: NotRequired[float] + n: NotRequired[float] + presence_penalty: NotRequired[float] + reasoning_budget: NotRequired[float] + reasoning_effort: NotRequired[Literal["none", "minimal", "low", "medium", "high"]] + reasoning_enabled: NotRequired[bool] + response_format: NotRequired[ResponseFormatNullish] + stop: NotRequired[Sequence[str]] + temperature: NotRequired[float] + tool_choice: NotRequired[ + Literal["auto"] | Literal["none"] | Literal["required"] | ModelParamsModelParamsToolChoice + ] + top_p: NotRequired[float] + use_cache: NotRequired[bool] + verbosity: NotRequired[Literal["low", "medium", "high"]] + + +ModelParams: TypeAlias = ( + ModelParamsModelParams + | ModelParamsModelParams1 + | ModelParamsModelParams2 + | ModelParamsModelParams3 + | ModelParamsModelParams4 +) + + +class OnlineScoreConfig(TypedDict): + apply_to_root_span: NotRequired[bool | None] + """ + Whether to trigger online scoring on the root span of each trace. Only applies when scope is 'span' or unset. + """ + apply_to_span_names: NotRequired[Sequence[str] | None] + """ + Trigger online scoring on any spans with a name in this list. Only applies when scope is 'span' or unset. + """ + btql_filter: NotRequired[str | None] + """ + Filter logs using BTQL + """ + sampling_rate: float + """ + The sampling rate for online scoring + """ + scope: NotRequired[SpanScope | TraceScope | GroupScope | None] + """ + The scope at which to run the functions. Defaults to span-level execution. + """ + scorers: Sequence[Scorer] + """ + The list of functions to run for online scoring. Can include scorers, facets, or other function types. + """ + skip_logging: NotRequired[bool | None] + """ + Whether to skip adding scorer spans when computing scores + """ + + +class PatchExperiment(TypedDict): + base_exp_id: NotRequired[str | None] + """ + Id of default base experiment to compare against when viewing this experiment + """ + dataset_id: NotRequired[str | None] + """ + Identifier of the linked dataset, or null if the experiment is not linked to a dataset + """ + dataset_version: NotRequired[str | None] + """ + Version number of the linked dataset the experiment was run against. This can be used to reproduce the experiment after the dataset has been modified. + """ + description: NotRequired[str | None] + """ + Textual description of the experiment + """ + internal_metadata: NotRequired[PatchExperimentInternalMetadata | None] + """ + Braintrust-controlled metadata about the experiment. + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + User-controlled metadata about the experiment + """ + name: NotRequired[str | None] + """ + Name of the experiment. Within a project, experiment names are unique + """ + parameters_id: NotRequired[str | None] + """ + Identifier of the linked saved parameters object, or null if the experiment is not linked to saved parameters + """ + parameters_version: NotRequired[str | None] + """ + Version number of the linked saved parameters object the experiment was run against. + """ + public: NotRequired[bool | None] + """ + Whether or not the experiment is public. Public experiments can be viewed by anybody inside or outside the organization + """ + repo_info: NotRequired[RepoInfo | None] + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the experiment + """ + + +class PatchProject(TypedDict): + description: NotRequired[str | None] + name: NotRequired[str | None] + """ + Name of the project + """ + settings: NotRequired[ProjectSettings] + user_id: NotRequired[str | None] + + +class PatchProjectAutomationConfig1(TypedDict): + batch_size: NotRequired[float | None] + """ + The number of rows to export in each batch + """ + credentials: PatchProjectAutomationConfig1Credentials | PatchProjectAutomationConfig1Credentials1 + event_type: Literal["btql_export"] + """ + The type of automation. + """ + export_definition: ( + PatchProjectAutomationConfig1ExportDefinition + | PatchProjectAutomationConfig1ExportDefinition1 + | PatchProjectAutomationConfig1ExportDefinition2 + ) + """ + The definition of what to export + """ + export_path: str + """ + The path to export the results to. It should include the storage protocol and prefix, e.g. s3://bucket-name/path/to/export + """ + format: Literal["jsonl", "parquet"] + """ + The format to export the results in + """ + interval_seconds: float + """ + Perform the triggered action at most once in this interval of seconds + """ + scope: NotRequired[SpanScope | TraceScope | GroupScope | None] + """ + Execution scope for export automation. Defaults to span-level execution. + """ + status: NotRequired[AutomationStatus] + + +class PatchProjectAutomationConfig3(TypedDict): + event_type: Literal["retention"] + """ + The type of automation. + """ + object_type: RetentionObjectType + retention_days: float + """ + The number of days to retain the object + """ + + +class PatchRoleAddMemberPermission(TypedDict): + permission: Permission + restrict_object_type: NotRequired[AclObjectType | None] + + +class PatchRoleRemoveMemberPermission(TypedDict): + permission: Permission + restrict_object_type: NotRequired[AclObjectType | None] + + +class PatchRole(TypedDict): + add_member_permissions: NotRequired[Sequence[PatchRoleAddMemberPermission] | None] + """ + A list of permissions to add to the role + """ + add_member_roles: NotRequired[Sequence[str] | None] + """ + A list of role IDs to add to the role's inheriting-from set + """ + description: NotRequired[str | None] + """ + Textual description of the role + """ + name: NotRequired[str | None] + """ + Name of the role + """ + remove_member_permissions: NotRequired[Sequence[PatchRoleRemoveMemberPermission] | None] + """ + A list of permissions to remove from the role + """ + remove_member_roles: NotRequired[Sequence[str] | None] + """ + A list of role IDs to remove from the role's inheriting-from set + """ + + +class Project(TypedDict): + created: NotRequired[str | None] + """ + Date of project creation + """ + deleted_at: NotRequired[str | None] + """ + Date of project deletion, or null if the project is still active + """ + description: NotRequired[str | None] + """ + Textual description of the project + """ + id: str + """ + Unique identifier for the project + """ + name: str + """ + Name of the project + """ + org_id: str + """ + Unique id for the organization that the project belongs under + """ + settings: NotRequired[ProjectSettings | None] + user_id: NotRequired[str | None] + """ + Identifies the user who created the project + """ + + +class ProjectAutomationConfig1(TypedDict): + batch_size: NotRequired[float | None] + """ + The number of rows to export in each batch + """ + credentials: ProjectAutomationConfig1Credentials | ProjectAutomationConfig1Credentials1 + event_type: Literal["btql_export"] + """ + The type of automation. + """ + export_definition: ( + ProjectAutomationConfig1ExportDefinition + | ProjectAutomationConfig1ExportDefinition1 + | ProjectAutomationConfig1ExportDefinition2 + ) + """ + The definition of what to export + """ + export_path: str + """ + The path to export the results to. It should include the storage protocol and prefix, e.g. s3://bucket-name/path/to/export + """ + format: Literal["jsonl", "parquet"] + """ + The format to export the results in + """ + interval_seconds: float + """ + Perform the triggered action at most once in this interval of seconds + """ + scope: NotRequired[SpanScope | TraceScope | GroupScope | None] + """ + Execution scope for export automation. Defaults to span-level execution. + """ + status: NotRequired[AutomationStatus] + + +class ProjectAutomationConfig3(TypedDict): + event_type: Literal["retention"] + """ + The type of automation. + """ + object_type: RetentionObjectType + retention_days: float + """ + The number of days to retain the object + """ + + +class ProjectLogsEventClassification(TypedDict): + confidence: NotRequired[float | None] + """ + Optional confidence score for the classification + """ + id: str + """ + Stable classification identifier + """ + label: NotRequired[str] + """ + Original label of the classification item, which is useful for search and indexing purposes + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + Optional metadata associated with the classification + """ + source: NotRequired[SavedFunctionId] + + +ProjectScoreCategories: TypeAlias = Sequence[ProjectScoreCategory] | Mapping[str, float] | Sequence[str] | None + + +class ProjectScoreConfig(TypedDict): + condition: NotRequired[ProjectScoreCondition | None] + destination: NotRequired[str | None] + multi_select: NotRequired[bool | None] + object_types: NotRequired[Sequence[Literal["project_logs", "dataset", "experiment"]] | None] + online: NotRequired[OnlineScoreConfig | None] + visibility: NotRequired[ProjectScoreConfigVisibility | None] + + +class PromptBlockDataPromptBlockData(TypedDict): + messages: Sequence[ChatCompletionMessageParam] + tools: NotRequired[str] + type: Literal["chat"] + + +PromptBlockData: TypeAlias = PromptBlockDataPromptBlockData | PromptBlockDataPromptBlockData1 + + +class PromptBlockDataNullishPromptBlockDataNullish(TypedDict): + messages: Sequence[ChatCompletionMessageParam] + tools: NotRequired[str] + type: Literal["chat"] + + +PromptBlockDataNullish: TypeAlias = ( + PromptBlockDataNullishPromptBlockDataNullish | PromptBlockDataNullishPromptBlockDataNullish1 | None +) + + +class PromptOptionsNullish(TypedDict): + model: NotRequired[str] + params: NotRequired[ModelParams] + position: NotRequired[str] + + +class SpanAttributes(TypedDict): + name: NotRequired[str | None] + """ + Name of the span, for display purposes only + """ + purpose: NotRequired[Literal["scorer"] | None] + """ + A special value that indicates the span was generated by a scoring automation + """ + type: NotRequired[SpanType | None] + + +class TopicAutomationConfig(TypedDict): + backfill_time_range: NotRequired[str | TopicAutomationConfigBackfillTimeRange | None] + """ + Topic window used for classification coverage and initial backfill. + """ + btql_filter: NotRequired[str | None] + """ + Optional BTQL filter applied before topic automation. + """ + data_scope: NotRequired[TopicAutomationDataScope] + event_type: Literal["topic"] + """ + The type of automation. + """ + facet_functions: Sequence[FacetFunction] + """ + Facet functions used by the topic automation + """ + facet_model: NotRequired[TopicAutomationFacetModel | None] + relabel_overlap_seconds: NotRequired[float | None] + """ + How much recent history to relabel after a new topic map version becomes active + """ + rerun_seconds: NotRequired[float | None] + """ + How often to recompute topic maps + """ + sampling_rate: float + """ + The sampling rate for topic automation + """ + scope: NotRequired[SpanScope | TraceScope | GroupScope | None] + """ + Execution scope for topic automation. Defaults to span-level execution. + """ + status: NotRequired[AutomationStatus] + topic_map_functions: Sequence[TopicMapFunctionAutomation] + """ + Topic map functions with optional per-topic-map filters + """ + + +class TopicMapData(TypedDict): + automation_btql_filter: NotRequired[str] + """ + Automation-level BTQL filter that was applied when this version was generated. Absent on versions generated before this was recorded. + """ + btql_filter: NotRequired[str] + """ + Per-topic-map BTQL filter that was applied when this version was generated. Absent on versions generated before this was recorded. + """ + bundle_key: NotRequired[str] + """ + Key of the topic map bundle in code_bundles bucket + """ + disable_reconciliation: NotRequired[bool] + """ + Whether new topic generation should ignore the previously saved report during reconciliation. Defaults to false when omitted. + """ + distance_threshold: NotRequired[float] + """ + Maximum distance to nearest centroid. If exceeded, returns no_match. + """ + embedding_model: str + """ + The embedding model to use for embedding facet values + """ + generation_settings: NotRequired[TopicMapGenerationSettings] + report_key: NotRequired[str] + """ + Key of the clustering report in code_bundles bucket + """ + source_facet: str + """ + The facet field name to use as input for classification + """ + topic_names: NotRequired[Mapping[str, str]] + """ + Mapping from topic_id to topic name + """ + type: Literal["topic_map"] + + +class ViewData(TypedDict): + custom_charts: NotRequired[Any | None] + search: NotRequired[ViewDataSearch | None] + + +class AclBatchUpdateRequest(TypedDict): + add_acls: NotRequired[Sequence[AclItem] | None] + remove_acls: NotRequired[Sequence[AclItem] | None] + + +class BatchedFacetDataTopicMap(TypedDict): + function_name: str + """ + The name of the topic map function + """ + topic_map_data: TopicMapData + topic_map_id: NotRequired[str] + """ + The id of the topic map function + """ + + +class BatchedFacetData(TypedDict): + facets: Sequence[BatchedFacetDataFacet] + preprocessor: NotRequired[Preprocessor] + topic_maps: NotRequired[Mapping[str, Sequence[BatchedFacetDataTopicMap]]] + """ + Topic maps that depend on facets in this batch, keyed by source facet name. Each source facet can have multiple topic maps. + """ + type: Literal["batched_facet"] + + +class CreateProjectAutomation(TypedDict): + config: ( + CreateProjectAutomationConfig + | CreateProjectAutomationConfig1 + | CreateProjectAutomationConfig2 + | CreateProjectAutomationConfig3 + | CreateProjectAutomationConfig4 + | TopicAutomationConfig + | TopicDigestAutomationConfig + ) + """ + The configuration for the automation rule + """ + description: NotRequired[str | None] + """ + Textual description of the project automation + """ + name: str + """ + Name of the project automation + """ + project_id: str + """ + Unique identifier for the project that the project automation belongs under + """ + + +class CreateProjectScore(TypedDict): + categories: NotRequired[ProjectScoreCategories] + config: NotRequired[ProjectScoreConfig | None] + description: NotRequired[str | None] + """ + Textual description of the project score + """ + name: str + """ + Name of the project score + """ + project_id: str + """ + Unique identifier for the project that the project score belongs under + """ + score_type: ProjectScoreType + + +class CreateView(TypedDict): + deleted_at: NotRequired[str | None] + """ + Date of role deletion, or null if the role is still active + """ + name: str + """ + Name of the view + """ + object_id: str + """ + The id of the object the view applies to + """ + object_type: AclObjectType + options: NotRequired[ViewOptions] + user_id: NotRequired[str | None] + """ + Identifies the user who created the view + """ + view_data: NotRequired[ViewData | None] + view_type: ( + Literal[ + "projects", + "experiments", + "experiment", + "playgrounds", + "playground", + "datasets", + "dataset", + "prompts", + "parameters", + "tools", + "scorers", + "classifiers", + "logs", + "monitor", + "for_review_project_log", + "for_review_experiments", + "for_review_datasets", + ] + | None + ) + """ + Type of object that the view corresponds to. + """ + + +class CrossObjectInsertRequestDataset(TypedDict): + events: NotRequired[Sequence[InsertDatasetEvent] | None] + """ + A list of dataset events to insert + """ + feedback: NotRequired[Sequence[FeedbackDatasetItem] | None] + """ + A list of dataset feedback items + """ + + +class ExperimentEvent(TypedDict): + field_pagination_key: NotRequired[str | None] + """ + A stable, time-ordered key that can be used to paginate over experiment events. This field is auto-generated by Braintrust and only exists in Brainstore. + """ + field_xact_id: str + """ + The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the experiment (see the `version` parameter) + """ + audit_data: NotRequired[Sequence[Any] | None] + """ + Optional list of audit entries attached to this event + """ + classifications: NotRequired[Mapping[str, Sequence[ExperimentEventClassification]] | None] + """ + Classifications for this event (dictionary from classification name to items) + """ + comments: NotRequired[Sequence[Any] | None] + """ + Optional list of comments attached to this event + """ + context: NotRequired[ExperimentEventContext | None] + """ + Context is additional information about the code that produced the experiment event. It is essentially the textual counterpart to `metrics`. Use the `caller_*` attributes to track the location in code which produced the experiment event + """ + created: str + """ + The timestamp the experiment event was created + """ + error: NotRequired[Any | None] + """ + The error that occurred, if any. + """ + expected: NotRequired[Any | None] + """ + The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate your experiments while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models + """ + experiment_id: str + """ + Unique identifier for the experiment + """ + facets: NotRequired[Mapping[str, str | None] | None] + """ + Facets for categorization (dictionary from facet id to value) + """ + id: str + """ + A unique identifier for the experiment event. If you don't provide one, Braintrust will generate one for you + """ + input: NotRequired[Any | None] + """ + The arguments that uniquely define a test case (an arbitrary, JSON serializable object). Later on, Braintrust will use the `input` to know whether two test cases are the same between experiments, so they should not contain experiment-specific state. A simple rule of thumb is that if you run the same experiment twice, the `input` should be identical + """ + is_root: NotRequired[bool | None] + """ + Whether this span is a root span + """ + metadata: NotRequired[ExperimentEventMetadata | None] + """ + A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings + """ + metrics: NotRequired[ExperimentEventMetrics | None] + """ + Metrics are numerical measurements tracking the execution of the code that produced the experiment event. Use "start" and "end" to track the time span over which the experiment event was produced + """ + origin: NotRequired[ObjectReferenceNullish | None] + output: NotRequired[Any | None] + """ + The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question + """ + project_id: str + """ + Unique identifier for the project that the experiment belongs under + """ + root_span_id: str + """ + A unique identifier for the trace this experiment event belongs to + """ + scores: NotRequired[Mapping[str, float | None] | None] + """ + A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was covering similar concepts or not. You can use these scores to help you sort, filter, and compare experiments + """ + span_attributes: NotRequired[SpanAttributes | None] + span_id: str + """ + A unique identifier used to link different experiment events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing + """ + span_parents: NotRequired[Sequence[str] | None] + """ + An array of the parent `span_ids` of this experiment event. This should be empty for the root span of a trace, and should most often contain just one parent element for subspans + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags to log + """ + + +class FetchExperimentEventsResponse(TypedDict): + cursor: NotRequired[str | None] + """ + Pagination cursor + + Pass this string directly as the `cursor` param to your next fetch request to get the next page of results. Not provided if the returned result set is empty. + """ + events: Sequence[ExperimentEvent] + """ + A list of fetched events + """ + + +class GraphNodeGraphNode7(TypedDict): + description: NotRequired[str | None] + """ + The description of the node + """ + position: NotRequired[GraphNodeGraphNode7Position | None] + """ + The position of the node + """ + prompt: PromptBlockData + type: Literal["prompt_template"] + + +GraphNode: TypeAlias = ( + GraphNodeGraphNode + | GraphNodeGraphNode1 + | GraphNodeGraphNode2 + | GraphNodeGraphNode3 + | GraphNodeGraphNode4 + | GraphNodeGraphNode5 + | GraphNodeGraphNode6 + | GraphNodeGraphNode7 +) + + +class InsertExperimentEvent(TypedDict): + field_array_delete: NotRequired[Sequence[InsertExperimentEventFieldArrayDeleteItem] | None] + """ + The `_array_delete` field allows removing specific values from array fields. It is an array of objects with `path` and `delete` properties. + + For example, to remove tags "foo" and "bar" from an existing row: `{"_is_merge": true, "_array_delete": [{"path": ["tags"], "delete": ["foo", "bar"]}]}`. For nested fields like `metadata.categories`, use `[{"path": ["metadata", "categories"], "delete": ["value"]}]`. This will remove those specific values from the array while preserving others. + """ + field_is_merge: NotRequired[bool | None] + """ + The `_is_merge` field controls how the row is merged with any existing row with the same id in the DB. By default (or when set to `false`), the existing row is completely replaced by the new row. When set to `true`, the new row is deep-merged into the existing row, if one is found. If no existing row is found, the new row is inserted as is. + + For example, say there is an existing row in the DB `{"id": "foo", "input": {"a": 5, "b": 10}}`. If we merge a new row as `{"_is_merge": true, "id": "foo", "input": {"b": 11, "c": 20}}`, the new row will be `{"id": "foo", "input": {"a": 5, "b": 11, "c": 20}}`. If we replace the new row as `{"id": "foo", "input": {"b": 11, "c": 20}}`, the new row will be `{"id": "foo", "input": {"b": 11, "c": 20}}` + """ + field_merge_paths: NotRequired[Sequence[Sequence[str]] | None] + """ + The `_merge_paths` field allows controlling the depth of the merge, when `_is_merge=true`. `_merge_paths` is a list of paths, where each path is a list of field names. The deep merge will not descend below any of the specified merge paths. + + For example, say there is an existing row in the DB `{"id": "foo", "input": {"a": {"b": 10}, "c": {"d": 20}}, "output": {"a": 20}}`. If we merge a new row as `{"_is_merge": true, "_merge_paths": [["input", "a"], ["output"]], "input": {"a": {"q": 30}, "c": {"e": 30}, "bar": "baz"}, "output": {"d": 40}}`, the new row will be `{"id": "foo": "input": {"a": {"q": 30}, "c": {"d": 20, "e": 30}, "bar": "baz"}, "output": {"d": 40}}`. In this case, due to the merge paths, we have replaced `input.a` and `output`, but have still deep-merged `input` and `input.c`. + """ + field_object_delete: NotRequired[bool | None] + """ + Pass `_object_delete=true` to mark the experiment event deleted. Deleted events will not show up in subsequent fetches for this experiment + """ + field_parent_id: NotRequired[str | None] + """ + DEPRECATED: The `_parent_id` field is deprecated and should not be used. Support for `_parent_id` will be dropped in a future version of Braintrust. Log `span_id`, `root_span_id`, and `span_parents` explicitly instead. + + Use the `_parent_id` field to create this row as a subspan of an existing row. Tracking hierarchical relationships are important for tracing (see the [guide](https://www.braintrust.dev/docs/instrument) for full details). + + For example, say we have logged a row `{"id": "abc", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"_parent_id": "abc", "id": "llm_call", "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + context: NotRequired[InsertExperimentEventContext | None] + """ + Context is additional information about the code that produced the experiment event. It is essentially the textual counterpart to `metrics`. Use the `caller_*` attributes to track the location in code which produced the experiment event + """ + created: NotRequired[str | None] + """ + The timestamp the experiment event was created + """ + error: NotRequired[Any | None] + """ + The error that occurred, if any. + """ + expected: NotRequired[Any | None] + """ + The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate your experiments while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models + """ + facets: NotRequired[Mapping[str, str | None] | None] + """ + Facets for categorization (dictionary from facet id to value) + """ + id: NotRequired[str | None] + """ + A unique identifier for the experiment event. If you don't provide one, Braintrust will generate one for you + """ + input: NotRequired[Any | None] + """ + The arguments that uniquely define a test case (an arbitrary, JSON serializable object). Later on, Braintrust will use the `input` to know whether two test cases are the same between experiments, so they should not contain experiment-specific state. A simple rule of thumb is that if you run the same experiment twice, the `input` should be identical + """ + metadata: NotRequired[InsertExperimentEventMetadata | None] + """ + A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings + """ + metrics: NotRequired[InsertExperimentEventMetrics | None] + """ + Metrics are numerical measurements tracking the execution of the code that produced the experiment event. Use "start" and "end" to track the time span over which the experiment event was produced + """ + origin: NotRequired[ObjectReferenceNullish | None] + output: NotRequired[Any | None] + """ + The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question + """ + root_span_id: NotRequired[str | None] + """ + Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details. + + For example, say we have logged a row `{"id": "abc", "span_id": "span0", "root_span_id": "root_span0", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"id": "llm_call", "span_id": "span1", "root_span_id": "root_span0", "span_parents": ["span0"], "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + scores: NotRequired[Mapping[str, float | None] | None] + """ + A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was covering similar concepts or not. You can use these scores to help you sort, filter, and compare experiments + """ + span_attributes: NotRequired[SpanAttributes | None] + span_id: NotRequired[str | None] + """ + Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details. + + For example, say we have logged a row `{"id": "abc", "span_id": "span0", "root_span_id": "root_span0", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"id": "llm_call", "span_id": "span1", "root_span_id": "root_span0", "span_parents": ["span0"], "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + span_parents: NotRequired[Sequence[str] | None] + """ + Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details. + + For example, say we have logged a row `{"id": "abc", "span_id": "span0", "root_span_id": "root_span0", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"id": "llm_call", "span_id": "span1", "root_span_id": "root_span0", "span_parents": ["span0"], "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags to log + """ + + +class InsertExperimentEventRequest(TypedDict): + events: Sequence[InsertExperimentEvent] + """ + A list of experiment events to insert + """ + + +class InsertProjectLogsEvent(TypedDict): + field_array_delete: NotRequired[Sequence[InsertProjectLogsEventFieldArrayDeleteItem] | None] + """ + The `_array_delete` field allows removing specific values from array fields. It is an array of objects with `path` and `delete` properties. + + For example, to remove tags "foo" and "bar" from an existing row: `{"_is_merge": true, "_array_delete": [{"path": ["tags"], "delete": ["foo", "bar"]}]}`. For nested fields like `metadata.categories`, use `[{"path": ["metadata", "categories"], "delete": ["value"]}]`. This will remove those specific values from the array while preserving others. + """ + field_is_merge: NotRequired[bool | None] + """ + The `_is_merge` field controls how the row is merged with any existing row with the same id in the DB. By default (or when set to `false`), the existing row is completely replaced by the new row. When set to `true`, the new row is deep-merged into the existing row, if one is found. If no existing row is found, the new row is inserted as is. + + For example, say there is an existing row in the DB `{"id": "foo", "input": {"a": 5, "b": 10}}`. If we merge a new row as `{"_is_merge": true, "id": "foo", "input": {"b": 11, "c": 20}}`, the new row will be `{"id": "foo", "input": {"a": 5, "b": 11, "c": 20}}`. If we replace the new row as `{"id": "foo", "input": {"b": 11, "c": 20}}`, the new row will be `{"id": "foo", "input": {"b": 11, "c": 20}}` + """ + field_merge_paths: NotRequired[Sequence[Sequence[str]] | None] + """ + The `_merge_paths` field allows controlling the depth of the merge, when `_is_merge=true`. `_merge_paths` is a list of paths, where each path is a list of field names. The deep merge will not descend below any of the specified merge paths. + + For example, say there is an existing row in the DB `{"id": "foo", "input": {"a": {"b": 10}, "c": {"d": 20}}, "output": {"a": 20}}`. If we merge a new row as `{"_is_merge": true, "_merge_paths": [["input", "a"], ["output"]], "input": {"a": {"q": 30}, "c": {"e": 30}, "bar": "baz"}, "output": {"d": 40}}`, the new row will be `{"id": "foo": "input": {"a": {"q": 30}, "c": {"d": 20, "e": 30}, "bar": "baz"}, "output": {"d": 40}}`. In this case, due to the merge paths, we have replaced `input.a` and `output`, but have still deep-merged `input` and `input.c`. + """ + field_object_delete: NotRequired[bool | None] + """ + Pass `_object_delete=true` to mark the project logs event deleted. Deleted events will not show up in subsequent fetches for this project logs + """ + field_parent_id: NotRequired[str | None] + """ + DEPRECATED: The `_parent_id` field is deprecated and should not be used. Support for `_parent_id` will be dropped in a future version of Braintrust. Log `span_id`, `root_span_id`, and `span_parents` explicitly instead. + + Use the `_parent_id` field to create this row as a subspan of an existing row. Tracking hierarchical relationships are important for tracing (see the [guide](https://www.braintrust.dev/docs/instrument) for full details). + + For example, say we have logged a row `{"id": "abc", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"_parent_id": "abc", "id": "llm_call", "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + context: NotRequired[InsertProjectLogsEventContext | None] + """ + Context is additional information about the code that produced the project logs event. It is essentially the textual counterpart to `metrics`. Use the `caller_*` attributes to track the location in code which produced the project logs event + """ + created: NotRequired[str | None] + """ + The timestamp the project logs event was created + """ + error: NotRequired[Any | None] + """ + The error that occurred, if any. + """ + expected: NotRequired[Any | None] + """ + The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models. + """ + facets: NotRequired[Mapping[str, str | None] | None] + """ + Facets for categorization (dictionary from facet id to value) + """ + id: NotRequired[str | None] + """ + A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you + """ + input: NotRequired[Any | None] + """ + The arguments that uniquely define a user input (an arbitrary, JSON serializable object). + """ + metadata: NotRequired[InsertProjectLogsEventMetadata | None] + """ + A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings + """ + metrics: NotRequired[InsertProjectLogsEventMetrics | None] + """ + Metrics are numerical measurements tracking the execution of the code that produced the project logs event. Use "start" and "end" to track the time span over which the project logs event was produced + """ + origin: NotRequired[ObjectReferenceNullish | None] + output: NotRequired[Any | None] + """ + The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question. + """ + root_span_id: NotRequired[str | None] + """ + Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details. + + For example, say we have logged a row `{"id": "abc", "span_id": "span0", "root_span_id": "root_span0", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"id": "llm_call", "span_id": "span1", "root_span_id": "root_span0", "span_parents": ["span0"], "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + scores: NotRequired[Mapping[str, float | None] | None] + """ + A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was covering similar concepts or not. You can use these scores to help you sort, filter, and compare logs. + """ + span_attributes: NotRequired[SpanAttributes | None] + span_id: NotRequired[str | None] + """ + Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details. + + For example, say we have logged a row `{"id": "abc", "span_id": "span0", "root_span_id": "root_span0", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"id": "llm_call", "span_id": "span1", "root_span_id": "root_span0", "span_parents": ["span0"], "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + span_parents: NotRequired[Sequence[str] | None] + """ + Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which is now deprecated. The span_id is a unique identifier describing the row's place in the a trace, and the root_span_id is a unique identifier for the whole trace. See the [guide](https://www.braintrust.dev/docs/instrument) for full details. + + For example, say we have logged a row `{"id": "abc", "span_id": "span0", "root_span_id": "root_span0", "input": "foo", "output": "bar", "expected": "boo", "scores": {"correctness": 0.33}}`. We can create a sub-span of the parent row by logging `{"id": "llm_call", "span_id": "span1", "root_span_id": "root_span0", "span_parents": ["span0"], "input": {"prompt": "What comes after foo?"}, "output": "bar", "metrics": {"tokens": 1}}`. In the webapp, only the root span row `"abc"` will show up in the summary view. You can view the full trace hierarchy (in this case, the `"llm_call"` row) by clicking on the "abc" row. + + If the row is being merged into an existing row, this field will be ignored. + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags to log + """ + + +class InsertProjectLogsEventRequest(TypedDict): + events: Sequence[InsertProjectLogsEvent] + """ + A list of project logs events to insert + """ + + +class PatchProjectAutomation(TypedDict): + config: NotRequired[ + PatchProjectAutomationConfig + | PatchProjectAutomationConfig1 + | PatchProjectAutomationConfig2 + | PatchProjectAutomationConfig3 + | PatchProjectAutomationConfig4 + | TopicAutomationConfig + | TopicDigestAutomationConfig + | Any + ] + """ + The configuration for the automation rule + """ + description: NotRequired[str | None] + """ + Textual description of the project automation + """ + name: NotRequired[str | None] + """ + Name of the project automation + """ + + +class PatchProjectScore(TypedDict): + categories: NotRequired[ProjectScoreCategories] + config: NotRequired[ProjectScoreConfig | None] + description: NotRequired[str | None] + """ + Textual description of the project score + """ + name: NotRequired[str | None] + """ + Name of the project score + """ + score_type: NotRequired[ProjectScoreType | None] + + +class PatchView(TypedDict): + name: NotRequired[str | None] + """ + Name of the view + """ + object_id: str + """ + The id of the object the view applies to + """ + object_type: AclObjectType + options: NotRequired[ViewOptions] + user_id: NotRequired[str | None] + """ + Identifies the user who created the view + """ + view_data: NotRequired[ViewData | None] + view_type: NotRequired[ + Literal[ + "projects", + "experiments", + "experiment", + "playgrounds", + "playground", + "datasets", + "dataset", + "prompts", + "parameters", + "tools", + "scorers", + "classifiers", + "logs", + "monitor", + "for_review_project_log", + "for_review_experiments", + "for_review_datasets", + ] + | None + ] + """ + Type of object that the view corresponds to. + """ + + +class ProjectAutomation(TypedDict): + config: ( + ProjectAutomationConfig + | ProjectAutomationConfig1 + | ProjectAutomationConfig2 + | ProjectAutomationConfig3 + | ProjectAutomationConfig4 + | TopicAutomationConfig + | TopicDigestAutomationConfig + ) + """ + The configuration for the automation rule + """ + created: NotRequired[str | None] + """ + Date of project automation creation + """ + description: NotRequired[str | None] + """ + Textual description of the project automation + """ + id: str + """ + Unique identifier for the project automation + """ + name: str + """ + Name of the project automation + """ + project_id: str + """ + Unique identifier for the project that the project automation belongs under + """ + user_id: NotRequired[str | None] + """ + Identifies the user who created the project automation + """ + + +class ProjectLogsEvent(TypedDict): + field_async_scoring_state: NotRequired[Any | None] + """ + The async scoring state for this event + """ + field_pagination_key: NotRequired[str | None] + """ + A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore. + """ + field_xact_id: str + """ + The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter) + """ + audit_data: NotRequired[Sequence[Any] | None] + """ + Optional list of audit entries attached to this event + """ + classifications: NotRequired[Mapping[str, Sequence[ProjectLogsEventClassification]] | None] + """ + Classifications for this event (dictionary from classification name to items) + """ + comments: NotRequired[Sequence[Any] | None] + """ + Optional list of comments attached to this event + """ + context: NotRequired[ProjectLogsEventContext | None] + """ + Context is additional information about the code that produced the project logs event. It is essentially the textual counterpart to `metrics`. Use the `caller_*` attributes to track the location in code which produced the project logs event + """ + created: str + """ + The timestamp the project logs event was created + """ + error: NotRequired[Any | None] + """ + The error that occurred, if any. + """ + expected: NotRequired[Any | None] + """ + The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models. + """ + facets: NotRequired[Mapping[str, str | None] | None] + """ + Facets for categorization (dictionary from facet id to value) + """ + id: str + """ + A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you + """ + input: NotRequired[Any | None] + """ + The arguments that uniquely define a user input (an arbitrary, JSON serializable object). + """ + is_root: NotRequired[bool | None] + """ + Whether this span is a root span + """ + log_id: Literal["g"] + """ + A literal 'g' which identifies the log as a project log + """ + metadata: NotRequired[ProjectLogsEventMetadata | None] + """ + A dictionary with additional data about the test example, model outputs, or just about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any JSON-serializable type, but its keys must be strings + """ + metrics: NotRequired[ProjectLogsEventMetrics | None] + """ + Metrics are numerical measurements tracking the execution of the code that produced the project logs event. Use "start" and "end" to track the time span over which the project logs event was produced + """ + org_id: str + """ + Unique id for the organization that the project belongs under + """ + origin: NotRequired[ObjectReferenceNullish | None] + output: NotRequired[Any | None] + """ + The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question. + """ + project_id: str + """ + Unique identifier for the project + """ + root_span_id: str + """ + A unique identifier for the trace this project logs event belongs to + """ + scores: NotRequired[Mapping[str, float | None] | None] + """ + A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was covering similar concepts or not. You can use these scores to help you sort, filter, and compare logs. + """ + span_attributes: NotRequired[SpanAttributes | None] + span_id: str + """ + A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing + """ + span_parents: NotRequired[Sequence[str] | None] + """ + An array of the parent `span_ids` of this project logs event. This should be empty for the root span of a trace, and should most often contain just one parent element for subspans + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags to log + """ + + +class ProjectScore(TypedDict): + categories: NotRequired[ProjectScoreCategories] + config: NotRequired[ProjectScoreConfig | None] + created: NotRequired[str | None] + """ + Date of project score creation + """ + description: NotRequired[str | None] + """ + Textual description of the project score + """ + id: str + """ + Unique identifier for the project score + """ + name: str + """ + Name of the project score + """ + position: NotRequired[str | None] + """ + An optional LexoRank-based string that sets the sort position for the score in the UI + """ + project_id: str + """ + Unique identifier for the project that the project score belongs under + """ + score_type: ProjectScoreType + user_id: str + + +class PromptData(TypedDict): + mcp: NotRequired[Mapping[str, PromptDataMcp | PromptDataMcp1] | None] + options: NotRequired[PromptOptionsNullish | None] + origin: NotRequired[PromptDataOrigin | None] + parser: NotRequired[PromptParserNullish | None] + prompt: NotRequired[PromptBlockDataNullish] + template_format: NotRequired[Literal["mustache", "nunjucks", "none"] | None] + tool_functions: NotRequired[Sequence[ToolFunction] | None] + + +class PromptDataNullish(TypedDict): + mcp: NotRequired[Mapping[str, PromptDataNullishMcp | PromptDataNullishMcp1] | None] + options: NotRequired[PromptOptionsNullish | None] + origin: NotRequired[PromptDataNullishOrigin | None] + parser: NotRequired[PromptParserNullish | None] + prompt: NotRequired[PromptBlockDataNullish] + template_format: NotRequired[Literal["mustache", "nunjucks", "none"] | None] + tool_functions: NotRequired[Sequence[ToolFunction1] | None] + + +class ScoreScore5(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + inline_function: Mapping[str, Any] + inline_prompt: NotRequired[PromptData] + name: NotRequired[str | None] + """ + The name of the inline function + """ + + +class ScoreScore6(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + inline_prompt: PromptData + name: NotRequired[str | None] + """ + The name of the inline prompt + """ + + +class ScoreScore13(ScoreScore5, ScoreScore7): + pass + + +class ScoreScore14(ScoreScore6, ScoreScore7): + pass + + +Score: TypeAlias = ScoreScore8 | ScoreScore9 | ScoreScore10 | ScoreScore11 | ScoreScore12 | ScoreScore13 | ScoreScore14 + + +class View(TypedDict): + created: NotRequired[str | None] + """ + Date of view creation + """ + deleted_at: NotRequired[str | None] + """ + Date of role deletion, or null if the role is still active + """ + id: str + """ + Unique identifier for the view + """ + name: str + """ + Name of the view + """ + object_id: str + """ + The id of the object the view applies to + """ + object_type: AclObjectType + options: NotRequired[ViewOptions] + user_id: NotRequired[str | None] + """ + Identifies the user who created the view + """ + view_data: NotRequired[ViewData | None] + view_type: ( + Literal[ + "projects", + "experiments", + "experiment", + "playgrounds", + "playground", + "datasets", + "dataset", + "prompts", + "parameters", + "tools", + "scorers", + "classifiers", + "logs", + "monitor", + "for_review_project_log", + "for_review_experiments", + "for_review_datasets", + ] + | None + ) + """ + Type of object that the view corresponds to. + """ + + +class CreatePrompt(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the prompt + """ + function_type: NotRequired[FunctionTypeEnumNullish | None] + name: str + """ + Name of the prompt + """ + project_id: str + """ + Unique identifier for the project that the prompt belongs under + """ + prompt_data: NotRequired[PromptDataNullish | None] + slug: str + """ + Unique identifier for the prompt + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the prompt + """ + + +class CrossObjectInsertRequestExperiment(TypedDict): + events: NotRequired[Sequence[InsertExperimentEvent] | None] + """ + A list of experiment events to insert + """ + feedback: NotRequired[Sequence[FeedbackExperimentItem] | None] + """ + A list of experiment feedback items + """ + + +class CrossObjectInsertRequestProjectLogs(TypedDict): + events: NotRequired[Sequence[InsertProjectLogsEvent] | None] + """ + A list of project logs events to insert + """ + feedback: NotRequired[Sequence[FeedbackProjectLogsItem] | None] + """ + A list of project logs feedback items + """ + + +class CrossObjectInsertRequest(TypedDict): + dataset: NotRequired[Mapping[str, CrossObjectInsertRequestDataset] | None] + """ + A mapping from dataset id to a set of log events and feedback items to insert + """ + experiment: NotRequired[Mapping[str, CrossObjectInsertRequestExperiment] | None] + """ + A mapping from experiment id to a set of log events and feedback items to insert + """ + project_logs: NotRequired[Mapping[str, CrossObjectInsertRequestProjectLogs] | None] + """ + A mapping from project id to a set of log events and feedback items to insert + """ + + +class FetchProjectLogsEventsResponse(TypedDict): + cursor: NotRequired[str | None] + """ + Pagination cursor + + Pass this string directly as the `cursor` param to your next fetch request to get the next page of results. Not provided if the returned result set is empty. + """ + events: Sequence[ProjectLogsEvent] + """ + A list of fetched events + """ + + +class FunctionIdFunctionId5(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + inline_function: Mapping[str, Any] + inline_prompt: NotRequired[PromptData] + name: NotRequired[str | None] + """ + The name of the inline function + """ + + +class FunctionIdFunctionId6(TypedDict): + function_type: NotRequired[FunctionTypeEnum] + inline_prompt: PromptData + name: NotRequired[str | None] + """ + The name of the inline prompt + """ + + +FunctionId: TypeAlias = ( + FunctionIdFunctionId + | FunctionIdFunctionId1 + | FunctionIdFunctionId2 + | FunctionIdFunctionId3 + | FunctionIdFunctionId4 + | FunctionIdFunctionId5 + | FunctionIdFunctionId6 +) +""" +The function to evaluate +""" + + +class GraphData(TypedDict): + edges: Mapping[str, GraphEdge] + nodes: Mapping[str, GraphNode] + type: Literal["graph"] + + +class PatchPrompt(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the prompt + """ + name: NotRequired[str | None] + """ + Name of the prompt + """ + prompt_data: NotRequired[PromptDataNullish | None] + slug: NotRequired[str | None] + """ + Unique identifier for the prompt + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the prompt + """ + + +class Prompt(TypedDict): + field_xact_id: str + """ + The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the prompt (see the `version` parameter) + """ + created: NotRequired[str | None] + """ + Date of prompt creation + """ + description: NotRequired[str | None] + """ + Textual description of the prompt + """ + function_type: NotRequired[FunctionTypeEnumNullish | None] + id: str + """ + Unique identifier for the prompt + """ + log_id: Literal["p"] + """ + A literal 'p' which identifies the object as a project prompt + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + User-controlled metadata about the prompt + """ + name: str + """ + Name of the prompt + """ + org_id: str + """ + Unique identifier for the organization + """ + project_id: str + """ + Unique identifier for the project that the prompt belongs under + """ + prompt_data: NotRequired[PromptDataNullish | None] + slug: str + """ + Unique identifier for the prompt + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the prompt + """ + + +class RunEval(TypedDict): + base_experiment_id: NotRequired[str | None] + """ + An optional experiment id to use as a base. If specified, the new experiment will be summarized and compared to this experiment. + """ + base_experiment_name: NotRequired[str | None] + """ + An optional experiment name to use as a base. If specified, the new experiment will be summarized and compared to this experiment. + """ + data: RunEvalData | RunEvalData1 | RunEvalData2 + """ + The dataset to use + """ + experiment_name: NotRequired[str] + """ + An optional name for the experiment created by this eval. If it conflicts with an existing experiment, it will be suffixed with a unique identifier. + """ + extra_messages: NotRequired[str] + """ + A template path of extra messages to append to the conversion. These messages will be appended to the end of the conversation, after the last message. + """ + git_metadata_settings: NotRequired[GitMetadataSettings | None] + is_public: NotRequired[bool | None] + """ + Whether the experiment should be public. Defaults to false. + """ + max_concurrency: NotRequired[float | None] + """ + The maximum number of tasks/scorers that will be run concurrently. Defaults to 10. If null is provided, no max concurrency will be used. + """ + mcp_auth: NotRequired[Mapping[str, RunEvalMcpAuth]] + metadata: NotRequired[Mapping[str, Any]] + """ + Optional experiment-level metadata to store about the evaluation. You can later use this to slice & dice across experiments. + """ + name: NotRequired[str] + """ + The name of the eval to run when multiple evals available + """ + parameters: NotRequired[Mapping[str, Any]] + """ + Values for any parameters used in the eval + """ + parent: NotRequired[Parent] + project_id: str + """ + Unique identifier for the project to run the eval in + """ + repo_info: NotRequired[RepoInfo] + scores: Sequence[Score] + """ + The functions to score the eval on + """ + stop_token: NotRequired[str | None] + """ + The token to stop the run + """ + stream: NotRequired[bool] + """ + Whether to stream the results of the eval. If true, the request will return two events: one to indicate the experiment has started, and another upon completion. If false, the request will return the evaluation's summary upon completion. + """ + strict: NotRequired[bool | None] + """ + If true, throw an error if one of the variables in the prompt is not present in the input + """ + tags: NotRequired[Sequence[str]] + """ + Optional tags that will be added to the experiment. + """ + task: FunctionId + timeout: NotRequired[float | None] + """ + The maximum duration, in milliseconds, to run the evaluation. Defaults to undefined, in which case there is no timeout. + """ + trial_count: NotRequired[float | None] + """ + The number of times to run the evaluator per input. This is useful for evaluating applications that have non-deterministic behavior and gives you both a stronger aggregate measure and a sense of the variance in the results. + """ + + +FunctionData: TypeAlias = ( + FunctionDataFunctionData + | FunctionDataFunctionData1 + | GraphData + | FunctionDataFunctionData2 + | FunctionDataFunctionData3 + | FacetData + | BatchedFacetData + | FunctionDataFunctionData4 + | TopicMapData +) + + +FunctionDataNullish: TypeAlias = ( + FunctionDataNullishFunctionDataNullish + | FunctionDataNullishFunctionDataNullish1 + | GraphData + | FunctionDataNullishFunctionDataNullish2 + | FunctionDataNullishFunctionDataNullish3 + | FacetData + | BatchedFacetData + | FunctionDataNullishFunctionDataNullish4 + | TopicMapData + | None +) + + +class PatchFunction(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the prompt + """ + function_data: NotRequired[FunctionDataNullish] + name: NotRequired[str | None] + """ + Name of the prompt + """ + prompt_data: NotRequired[PromptDataNullish | None] + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the prompt + """ + + +class CreateFunction(TypedDict): + description: NotRequired[str | None] + """ + Textual description of the prompt + """ + function_data: FunctionData + function_schema: NotRequired[CreateFunctionFunctionSchema | None] + """ + JSON schema for the function's parameters and return type + """ + function_type: NotRequired[FunctionTypeEnumNullish | None] + name: str + """ + Name of the prompt + """ + origin: NotRequired[CreateFunctionOrigin | None] + project_id: str + """ + Unique identifier for the project that the prompt belongs under + """ + prompt_data: NotRequired[PromptDataNullish | None] + slug: str + """ + Unique identifier for the prompt + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the prompt + """ + + +class Function(TypedDict): + field_xact_id: str + """ + The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the prompt (see the `version` parameter) + """ + created: NotRequired[str | None] + """ + Date of prompt creation + """ + description: NotRequired[str | None] + """ + Textual description of the prompt + """ + function_data: FunctionData + function_schema: NotRequired[FunctionFunctionSchema | None] + """ + JSON schema for the function's parameters and return type + """ + function_type: NotRequired[FunctionTypeEnumNullish | None] + id: str + """ + Unique identifier for the prompt + """ + log_id: Literal["p"] + """ + A literal 'p' which identifies the object as a project prompt + """ + metadata: NotRequired[Mapping[str, Any] | None] + """ + User-controlled metadata about the prompt + """ + name: str + """ + Name of the prompt + """ + org_id: str + """ + Unique identifier for the organization + """ + origin: NotRequired[FunctionOrigin | None] + project_id: str + """ + Unique identifier for the project that the prompt belongs under + """ + prompt_data: NotRequired[PromptDataNullish | None] + slug: str + """ + Unique identifier for the prompt + """ + tags: NotRequired[Sequence[str] | None] + """ + A list of tags for the prompt + """ diff --git a/py/src/braintrust/api/test_generated_models.py b/py/src/braintrust/api/test_generated_models.py new file mode 100644 index 00000000..e83501d0 --- /dev/null +++ b/py/src/braintrust/api/test_generated_models.py @@ -0,0 +1,41 @@ +import importlib.resources +import json +import subprocess +import sys +from typing import is_typeddict + + +def test_import_braintrust_is_lazy_about_generated_api_modules(): + script = """ +import json +import sys +import braintrust +print(json.dumps(sorted(name for name in sys.modules if name.startswith('braintrust.api._generated')))) +""" + + result = subprocess.run([sys.executable, "-c", script], check=True, capture_output=True, text=True) + + assert json.loads(result.stdout) == [] + + +def test_generated_models_import_on_supported_python(): + from braintrust.api._generated import models + + assert is_typeddict(models.Project) + assert models.ProjectIdParam is str + + +def test_generated_package_content_is_installed(): + generated = importlib.resources.files("braintrust.api._generated") + + assert generated.joinpath("__init__.py").is_file() + assert generated.joinpath("models.py").is_file() + + +def test_rest_and_logging_type_surfaces_have_reviewed_overlap(): + from braintrust import generated_types + from braintrust.api import types + + overlap = set(generated_types.__all__) & set(types.__all__) + + assert overlap == set() diff --git a/py/src/braintrust/api/types/__init__.py b/py/src/braintrust/api/types/__init__.py new file mode 100644 index 00000000..86d08d26 --- /dev/null +++ b/py/src/braintrust/api/types/__init__.py @@ -0,0 +1,7 @@ +"""Public REST API types. + +No generated REST models are public yet. Types are added here deliberately as resource wrappers are +published; the private ``braintrust.api._generated`` package is not a compatibility surface. +""" + +__all__: list[str] = [] diff --git a/py/tests/api_codegen/conftest.py b/py/tests/api_codegen/conftest.py new file mode 100644 index 00000000..6df0bb4e --- /dev/null +++ b/py/tests/api_codegen/conftest.py @@ -0,0 +1,57 @@ +import copy +import sys +from pathlib import Path + +import pytest + + +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "scripts")) + +from openapi_codegen import CONFIG_PATH, load_config # noqa: E402 + + +@pytest.fixture +def codegen_config(): + config = copy.deepcopy(load_config(CONFIG_PATH)) + config["endpoint_generator"]["skip_tags"] = {} + return config + + +@pytest.fixture +def minimal_spec(): + return { + "openapi": "3.0.3", + "info": {"title": "Test", "version": "1"}, + "paths": { + "/widgets/{widget_id}": { + "get": { + "operationId": "getWidget", + "tags": ["Widgets"], + "parameters": [{"$ref": "#/components/parameters/WidgetId"}], + "responses": { + "200": { + "description": "OK", + "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Widget"}}}, + } + }, + } + } + }, + "components": { + "parameters": { + "WidgetId": { + "name": "widget_id", + "in": "path", + "required": True, + "schema": {"type": "string"}, + } + }, + "schemas": { + "Widget": { + "type": "object", + "properties": {"name": {"type": "string"}}, + "required": ["name"], + } + }, + }, + } diff --git a/py/tests/api_codegen/test_generation.py b/py/tests/api_codegen/test_generation.py new file mode 100644 index 00000000..203d28fe --- /dev/null +++ b/py/tests/api_codegen/test_generation.py @@ -0,0 +1,95 @@ +import copy +import re + +from openapi_codegen import atomic_replace_tree, compare_generated, generate_tree + + +def _generate(tmp_path, name, config, spec): + output = tmp_path / name / "_generated" + generate_tree(output, config, spec) + return output + + +def test_generation_is_byte_for_byte_deterministic(tmp_path, codegen_config, minimal_spec): + first = _generate(tmp_path, "first", codegen_config, minimal_spec) + second = _generate(tmp_path, "second", codegen_config, minimal_spec) + + assert compare_generated(first, second) == [] + + +def test_stale_artifacts_are_reported_and_removed(tmp_path, codegen_config, minimal_spec): + """Files the generator no longer emits count as drift, whatever their extension.""" + regenerated = _generate(tmp_path, "regenerated", codegen_config, minimal_spec) + committed = _generate(tmp_path, "committed", codegen_config, minimal_spec) + (committed / "endpoints.pyi").write_text("stale\n", encoding="utf-8") + stale_package = committed / "services" + stale_package.mkdir() + (stale_package / "__init__.py").write_text("stale\n", encoding="utf-8") + (stale_package / "__pycache__").mkdir() + + differences = compare_generated(regenerated, committed) + assert any("endpoints.pyi" in line for line in differences) + assert any("services/__init__.py" in line for line in differences) + + atomic_replace_tree(regenerated, committed) + + assert compare_generated(regenerated, committed) == [] + assert not (committed / "endpoints.pyi").exists() + assert not stale_package.exists() + + +def test_nullable_and_missing_fields_remain_distinct(tmp_path, codegen_config, minimal_spec): + spec = copy.deepcopy(minimal_spec) + widget = spec["components"]["schemas"]["Widget"] + widget["properties"] = { + "required_nullable": {"type": "string", "nullable": True}, + "optional_nullable": {"type": "string", "nullable": True}, + "optional_non_null": {"type": "string"}, + } + widget["required"] = ["required_nullable"] + + generated = _generate(tmp_path, "nullable", codegen_config, spec) + models = (generated / "models.py").read_text() + + assert re.search(r"required_nullable: str \| None", models) + assert re.search(r"optional_nullable: NotRequired\[str \| None\]", models) + assert re.search(r"optional_non_null: NotRequired\[str\]", models) + + +def test_composition_types_and_json_scalars_generate(tmp_path, codegen_config, minimal_spec): + spec = copy.deepcopy(minimal_spec) + spec["components"]["schemas"].update( + { + "Cat": { + "type": "object", + "properties": {"lives": {"type": "integer"}}, + "required": ["lives"], + }, + "Dog": { + "type": "object", + "properties": {"good": {"type": "boolean"}}, + "required": ["good"], + }, + "Pet": {"oneOf": [{"$ref": "#/components/schemas/Cat"}, {"$ref": "#/components/schemas/Dog"}]}, + "PetEnvelope": { + "allOf": [ + {"type": "object", "properties": {"pet": {"$ref": "#/components/schemas/Pet"}}}, + { + "type": "object", + "properties": { + "ratio": {"type": "number"}, + "labels": {"type": "array", "items": {"type": "string"}}, + }, + }, + ] + }, + } + ) + + generated = _generate(tmp_path, "composition", codegen_config, spec) + models = (generated / "models.py").read_text() + + assert re.search(r"Pet: TypeAlias = Cat \| Dog", models) + assert "class PetEnvelope" in models + assert "ratio: NotRequired[float]" in models + assert "labels: NotRequired[Sequence[str]]" in models diff --git a/py/tests/api_codegen/test_validation.py b/py/tests/api_codegen/test_validation.py new file mode 100644 index 00000000..bcaec1a2 --- /dev/null +++ b/py/tests/api_codegen/test_validation.py @@ -0,0 +1,206 @@ +import copy +import hashlib +import json + +import pytest +from openapi_codegen import ( + CodegenError, + normalize_spec, + read_and_verify_spec, + validate_config, + validate_spec, +) + + +def test_hash_and_full_commit_pin_validation(tmp_path, codegen_config, minimal_spec): + spec_path = tmp_path / "spec.json" + spec_path.write_text(json.dumps(minimal_spec, sort_keys=True), encoding="utf-8") + codegen_config["spec"]["sha256"] = hashlib.sha256(spec_path.read_bytes()).hexdigest() + + assert read_and_verify_spec(codegen_config, spec_path) == minimal_spec + + codegen_config["spec"]["sha256"] = "0" * 64 + with pytest.raises(CodegenError, match="spec hash mismatch"): + read_and_verify_spec(codegen_config, spec_path) + + codegen_config["spec"]["commit"] = "main" + with pytest.raises(CodegenError, match="full lowercase 40-character commit SHA"): + validate_config(codegen_config, check_installed_tools=False) + + +def test_normalization_removes_only_options_and_exact_skips(minimal_spec, codegen_config): + spec = copy.deepcopy(minimal_spec) + spec["paths"]["/widgets/{widget_id}"]["options"] = { + "operationId": "optionsWidget", + "tags": ["CORS"], + "responses": {"200": {"description": "OK", "content": {"text/plain": {"schema": {"type": "string"}}}}}, + } + spec["paths"]["/proxy"] = { + "post": { + "operationId": "proxyRequest", + "tags": ["Proxy"], + "responses": { + "200": { + "description": "OK", + "content": {"application/json": {"schema": {"type": "object"}}}, + } + }, + } + } + codegen_config["endpoint_generator"]["skip_tags"] = { + "Proxy": {"reason": "Specialized streaming transport", "operation_ids": ["proxyRequest"]} + } + + normalized = normalize_spec(spec, validate_spec(spec, codegen_config).skip_ids) + + assert set(normalized["paths"]) == {"/widgets/{widget_id}"} + assert set(normalized["paths"]["/widgets/{widget_id}"]) == {"get"} + + non_cors_options = copy.deepcopy(spec) + non_cors_options["paths"]["/widgets/{widget_id}"]["options"]["tags"] = ["Other"] + with pytest.raises(CodegenError, match="is not tagged only as CORS"): + validate_spec(non_cors_options, codegen_config) + + codegen_config["endpoint_generator"]["skip_tags"]["Proxy"]["operation_ids"] = [] + with pytest.raises(CodegenError, match="does not match the spec exactly"): + validate_spec(spec, codegen_config) + + +def test_invalid_and_duplicate_operation_ids_fail(minimal_spec, codegen_config): + spec = copy.deepcopy(minimal_spec) + spec["paths"]["/widgets/{widget_id}"]["get"]["operationId"] = "get-widget" + with pytest.raises(CodegenError, match="invalid operationId"): + validate_spec(spec, codegen_config) + + spec = copy.deepcopy(minimal_spec) + spec["paths"]["/other"] = copy.deepcopy(spec["paths"]["/widgets/{widget_id}"]) + spec["paths"]["/other"]["get"]["parameters"] = [] + with pytest.raises(CodegenError, match="Duplicate operationId"): + validate_spec(spec, codegen_config) + + +def test_duplicate_operation_ids_fail_even_when_one_copy_is_skipped(minimal_spec, codegen_config): + """A skipped duplicate must not silently take its supported twin out of the generated client.""" + spec = copy.deepcopy(minimal_spec) + duplicate = copy.deepcopy(spec["paths"]["/widgets/{widget_id}"]["get"]) + duplicate["parameters"] = [] + duplicate["tags"] = ["Proxy"] + spec["paths"]["/proxy"] = {"get": duplicate} + codegen_config["endpoint_generator"]["skip_tags"] = { + "Proxy": {"reason": "Specialized streaming transport", "operation_ids": ["getWidget"]} + } + + with pytest.raises(CodegenError, match="Duplicate operationId"): + validate_spec(spec, codegen_config) + + +def test_inline_operation_name_collisions_fail(minimal_spec, codegen_config): + spec = copy.deepcopy(minimal_spec) + second = copy.deepcopy(spec["paths"]["/widgets/{widget_id}"]["get"]) + second["operationId"] = "GetWidget" + second["parameters"] = [] + spec["paths"]["/other"] = {"get": second} + + with pytest.raises(CodegenError, match="Inline operation name collision"): + validate_spec(spec, codegen_config) + + +def test_schema_name_collisions_fail(minimal_spec, codegen_config): + spec = copy.deepcopy(minimal_spec) + spec["components"]["schemas"]["foo-bar"] = {"type": "string"} + spec["components"]["schemas"]["foo_bar"] = {"type": "string"} + + with pytest.raises(CodegenError, match="Schema name collision"): + validate_spec(spec, codegen_config) + + +def test_media_types_and_success_statuses_are_validated(minimal_spec, codegen_config): + spec = copy.deepcopy(minimal_spec) + operation = spec["paths"]["/widgets/{widget_id}"]["get"] + operation["requestBody"] = { + "content": {"application/xml": {"schema": {"type": "string"}}}, + "required": True, + } + with pytest.raises(CodegenError, match="unsupported request media type"): + validate_spec(spec, codegen_config) + + spec = copy.deepcopy(minimal_spec) + response = spec["paths"]["/widgets/{widget_id}"]["get"]["responses"].pop("200") + spec["paths"]["/widgets/{widget_id}"]["get"]["responses"]["206"] = response + with pytest.raises(CodegenError, match="unsupported success status"): + validate_spec(spec, codegen_config) + + spec = copy.deepcopy(minimal_spec) + content = spec["paths"]["/widgets/{widget_id}"]["get"]["responses"]["200"]["content"] + content["application/octet-stream"] = content.pop("application/json") + with pytest.raises(CodegenError, match="unsupported success response media type"): + validate_spec(spec, codegen_config) + + +def test_referenced_parameters_resolve_and_match_path(minimal_spec, codegen_config): + validate_spec(minimal_spec, codegen_config) + + spec = copy.deepcopy(minimal_spec) + spec["components"]["parameters"]["WidgetId"]["schema"] = {"type": "object"} + with pytest.raises(CodegenError, match="must be scalar"): + validate_spec(spec, codegen_config) + + spec = copy.deepcopy(minimal_spec) + spec["paths"]["/widgets/{widget_id}"]["get"]["parameters"][0]["$ref"] = "#/components/parameters/Missing" + with pytest.raises(CodegenError, match="Unresolved OpenAPI reference"): + validate_spec(spec, codegen_config) + + +def test_only_json_compatible_schema_types_and_values_are_supported(minimal_spec, codegen_config): + spec = copy.deepcopy(minimal_spec) + spec["components"]["schemas"]["Widget"]["properties"]["created"] = {"type": "date"} + with pytest.raises(CodegenError, match="Unsupported non-JSON schema type"): + validate_spec(spec, codegen_config) + + spec = copy.deepcopy(minimal_spec) + spec["components"]["schemas"]["Widget"]["properties"]["count"] = { + "type": "number", + "default": float("nan"), + } + with pytest.raises(CodegenError, match="not JSON-compatible"): + validate_spec(spec, codegen_config) + + +@pytest.mark.parametrize( + "keyword,subschema", + [ + ("patternProperties", {"^x-": {"type": "date"}}), + ("dependentSchemas", {"name": {"type": "date"}}), + ("propertyNames", {"type": "date"}), + ("prefixItems", [{"type": "date"}]), + ("if", {"type": "date"}), + ("contains", {"type": "date"}), + ], +) +def test_unsupported_types_are_caught_under_every_schema_keyword(minimal_spec, codegen_config, keyword, subschema): + spec = copy.deepcopy(minimal_spec) + spec["components"]["schemas"]["Widget"][keyword] = subschema + + with pytest.raises(CodegenError, match="Unsupported non-JSON schema type"): + validate_spec(spec, codegen_config) + + +def test_malformed_specs_and_configs_raise_actionable_errors(minimal_spec, codegen_config): + """Shape problems have to surface as CodegenError; a bare KeyError escapes the scripts' handler.""" + # A spec without any components is empty, not malformed -- it must not blow up on a missing key. + assert validate_spec({"openapi": "3.0.3", "paths": {}}, codegen_config).schema_count == 0 + with pytest.raises(CodegenError, match="components.schemas must be an object"): + validate_spec({"openapi": "3.0.3", "paths": {}, "components": {"schemas": []}}, codegen_config) + + spec = copy.deepcopy(minimal_spec) + spec["paths"]["/widgets/{widget_id}"]["get"]["responses"]["200"]["content"]["application/json"] = None + with pytest.raises(CodegenError, match="must be an object"): + validate_spec(spec, codegen_config) + + for key in ("supported_request_media_types", "supported_response_media_types", "supported_success_statuses"): + broken = copy.deepcopy(codegen_config) + del broken["endpoint_generator"][key] + with pytest.raises(CodegenError, match=f"endpoint_generator.{key} must be a non-empty list"): + validate_spec(minimal_spec, broken) + with pytest.raises(CodegenError, match=f"endpoint_generator.{key} must be a non-empty list"): + validate_config(broken, check_installed_tools=False) diff --git a/py/uv.lock b/py/uv.lock index 38b820f5..7675a95e 100644 --- a/py/uv.lock +++ b/py/uv.lock @@ -649,6 +649,50 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5", size = 32764, upload-time = "2024-02-18T19:09:04.156Z" }, ] +[[package]] +name = "black" +version = "26.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "pytokens" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-agentscope') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-agno') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-pydantic-ai-logfire') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-agno') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-pydantic-ai-logfire') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-pydantic-ai-otel-events') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-openai-agents' and extra == 'group-10-braintrust-test-strands')" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-agentscope') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-agno') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-pydantic-ai-logfire') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-agno') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-pydantic-ai-logfire') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-pydantic-ai-otel-events') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-openai-agents' and extra == 'group-10-braintrust-test-strands')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/37/5628dd55bf2b34257fc7603f0fe97c40e3aaf24265f416a9c85c95ca1436/black-26.5.1.tar.gz", hash = "sha256:dd321f668053961824bcc1be1cc1df748b2d7e4fa28086b08331e577b0100a73", size = 679439, upload-time = "2026-05-18T16:53:36.107Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/84/b3f55026206a9e8820a91503308075ca48eadc515e436731ca01dbe043b3/black-26.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9942db8888e06943c5dde66ca0037dcff82a2a4ec1ad0ada9e0d2ee9d9823893", size = 1987719, upload-time = "2026-05-18T17:05:02.757Z" }, + { url = "https://files.pythonhosted.org/packages/c6/34/7db312c5e5783d6e76cffd9d5ac8972a32badae4c6e3288dac0eed8d3bed/black-26.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:89c93167a74d3a75dfaa38a5c7cca015537d5820dd7f17d63267d674a61cae90", size = 1810083, upload-time = "2026-05-18T17:05:04.302Z" }, + { url = "https://files.pythonhosted.org/packages/33/e2/e0101e73c2c8727634e2efcb35e2b34bd23ad70dfa673789f5773a591b21/black-26.5.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22f2cd76d069cc54c71f10360744ba8983fbb616903b4304a85b734915c8e1b4", size = 1860633, upload-time = "2026-05-18T17:05:06.391Z" }, + { url = "https://files.pythonhosted.org/packages/b0/4c/e15c0c5b23cf3651035fe5addcce90e283af3548a3f91bb03d81b83106ab/black-26.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:87ed5c6f450580a2f6790bc7cbfb016dfc73bc750249762268a3695361315eef", size = 1477886, upload-time = "2026-05-18T17:05:07.96Z" }, + { url = "https://files.pythonhosted.org/packages/9f/3f/59d43ade98d2ce5c8dc34a4e46cbecd177e6d55d7d4092969c6003ccc655/black-26.5.1-cp310-cp310-win_arm64.whl", hash = "sha256:58b4bd92cf88aacf83d88479c8f9caee044b1ec55f2451a337354a7ea2590a22", size = 1277111, upload-time = "2026-05-18T17:05:09.473Z" }, + { url = "https://files.pythonhosted.org/packages/4b/96/3c3e09f09f44a37aac36b178a279cd19aa7001bd796187a7b162a294c81f/black-26.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:96ae2c733b2aabdd9986e2c5df628ff3473676cd1c5faded1ff496cf6d74083c", size = 1970639, upload-time = "2026-05-18T17:05:11.461Z" }, + { url = "https://files.pythonhosted.org/packages/83/ea/5ad117b9ee3ecd933c712bcbae610006e5b7cc9f41c526cd7ed3b6c4124c/black-26.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0e48b87e03bf109288e55cfceadcfa15ff5470aca2851a851950ed2926f450d7", size = 1792130, upload-time = "2026-05-18T17:05:12.983Z" }, + { url = "https://files.pythonhosted.org/packages/06/3a/7c448bc623fcdfa96672531beb5a616ea5e64f6975955254d7731ffb0ad9/black-26.5.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5119fa92ae61f786e8c3662fd60aece1d0a2dd5cca5d0c79417a95e7a4272a59", size = 1846134, upload-time = "2026-05-18T17:05:14.506Z" }, + { url = "https://files.pythonhosted.org/packages/a1/5b/0b39b3a5917f0657ac014ad2edb58c139553a478adfe7f817abf1622ff6e/black-26.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:30d3c14661f2792e9142cce3eeeb1cbc175b3eb5f733be0c8eeb99651e52b0c3", size = 1478883, upload-time = "2026-05-18T17:05:16.542Z" }, + { url = "https://files.pythonhosted.org/packages/4c/48/dc222692e0f95030db1bbfb6c857e76858bad09058221ea7aae815255327/black-26.5.1-cp311-cp311-win_arm64.whl", hash = "sha256:1ef92b76f7733f282fd096ea406200b5a286c42947412b0eaff3a74e3616cefe", size = 1277776, upload-time = "2026-05-18T17:05:18.029Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/7744b906703228264ef73bdd534df88ec1ef3de45c4e78f6d31b9e32d0c9/black-26.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4ad6fa01f941920f54f2bbb35f3df7673428a0ef98a0b0840c2eaef3b110efa8", size = 2012518, upload-time = "2026-05-18T17:05:20.108Z" }, + { url = "https://files.pythonhosted.org/packages/b7/c0/c5a3b1636dfd09c42534f2b3cf33506814f6d3e066fb0879ffa16c1ae860/black-26.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3915f256e75a2d7cf88d8953d37f780455dc586cc72dee059c528fe77f581217", size = 1816016, upload-time = "2026-05-18T17:05:21.84Z" }, + { url = "https://files.pythonhosted.org/packages/1f/0e/36044316b65ca471d3bb6d3703fd06fb50c6b727c3562f6a5a3153634f88/black-26.5.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d98d4137277c75dfb898ec8d846c4fd68ba1e9cf77f95e2865c203dc18f4c3d", size = 1884150, upload-time = "2026-05-18T17:05:23.546Z" }, + { url = "https://files.pythonhosted.org/packages/b3/33/dafc5808c2af43672912111d7c3354af1615f7e2be3bed7a878461abbe4d/black-26.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:a1dca32d9f1784af512a13410ec204c6f7f0aa9797a111c42e1c03449821c264", size = 1486825, upload-time = "2026-05-18T17:05:25.004Z" }, + { url = "https://files.pythonhosted.org/packages/82/14/b965ee6ad2a311f28bdbf692def3ee9848d2ae289dab28b27657fcee3e78/black-26.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:1037d5ac7b7b310b2632ad867ec8d0e4c4819dcdb0b820f63135da746a24e418", size = 1288646, upload-time = "2026-05-18T17:05:26.477Z" }, + { url = "https://files.pythonhosted.org/packages/3f/5c/c384363980e11e25ca6b93205949bb331fbf35f4e0dbec376dfa6326cec8/black-26.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2b36cf2ddf5566e205f6535f782a62194a184d33e175b64ae8c40b1737522be3", size = 2009020, upload-time = "2026-05-18T17:05:28.132Z" }, + { url = "https://files.pythonhosted.org/packages/0b/df/9f31c5e0babbfed77d505fc5d120beb98b21b33feaeded3924ea941fe360/black-26.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f7ea64ebfa01b50f693508fc39f875e264446d3b097088f84f203b9d09618a0", size = 1813335, upload-time = "2026-05-18T17:05:31.266Z" }, + { url = "https://files.pythonhosted.org/packages/fb/24/8e7b9a2fa61b0afd82209efe937557d180a1fa055bd7f6161eb9defc3719/black-26.5.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecb3e624844c798144e9bd986954e0adc81d8911a1f30f375e1252fe26e8c294", size = 1881614, upload-time = "2026-05-18T17:05:32.718Z" }, + { url = "https://files.pythonhosted.org/packages/49/ad/b4e0d9365ba8ac34f6bbab62a4b1b2dd5d618fac3fa1b8db968c844201b5/black-26.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:e1a26503279b6b310669fb0b219c39e4820b77e8189fe80f522bb511f247db0a", size = 1488925, upload-time = "2026-05-18T17:05:34.259Z" }, + { url = "https://files.pythonhosted.org/packages/a1/4b/652b859bf5df88a751c30451b09338f7fd26a77d1271c666992f836b7711/black-26.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c34b25da232ead53a6f335b76dbea124f4d152ad568b9080d6f944bc2b34b52", size = 1289883, upload-time = "2026-05-18T17:05:36.019Z" }, + { url = "https://files.pythonhosted.org/packages/a6/16/a8da8eb208c51c7f4ce74609a45d0dcc6d8a2141e45e81ee5289d1bb0d59/black-26.5.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e88976690a64b0af98312ca958415849cb42423423c5f2ee74af4b49a97a2168", size = 2004800, upload-time = "2026-05-18T17:05:38.182Z" }, + { url = "https://files.pythonhosted.org/packages/11/8a/a479296a19e383b70a725882a6cf3d786540601ff03cabbaaf1cce864c5a/black-26.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32d5ea7f6c8bdfa6e648326ebca1f02b0764e2a029edc6f8dce2627e19d468c3", size = 1815576, upload-time = "2026-05-18T17:05:40.309Z" }, + { url = "https://files.pythonhosted.org/packages/81/6b/cfaf3d39f25132c156a068f6b805576c9103a84086019507c70e1911ee7d/black-26.5.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea8d16dc41655aa113cd64665e7219446cd7e4ff2248d7178eaa905190c86b18", size = 1877927, upload-time = "2026-05-18T17:05:42.463Z" }, + { url = "https://files.pythonhosted.org/packages/66/76/302e313964bcff7e28df329d39f84f5270095730d85ff0acc260610a0d82/black-26.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:577f21094ea469ef92ec1adaf2c9441a226d2144d01a5be2fa823cecf6543e50", size = 1511860, upload-time = "2026-05-18T17:05:43.943Z" }, + { url = "https://files.pythonhosted.org/packages/27/4e/a3827e35e0e567f9f9ee59e2a0ab979267dca98718f25547ca8c6733afd4/black-26.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:ed1a20af114c301a0269bf01163d51dbef72737fd65f850001e7cbe7f3c7abae", size = 1316632, upload-time = "2026-05-18T17:05:45.521Z" }, + { url = "https://files.pythonhosted.org/packages/94/51/f975cae76d44274cc2868dc9040ac5d58d464784610234455b4e7b19c6ef/black-26.5.1-py3-none-any.whl", hash = "sha256:4ed7f7da04046d2e488437170797d3b4a4ad83906683bcb7dfc68b673bbce5e2", size = 213693, upload-time = "2026-05-18T16:53:33.964Z" }, +] + [[package]] name = "boto3" version = "1.43.67" @@ -740,10 +784,15 @@ temporal = [ ] [package.dev-dependencies] +api-codegen = [ + { name = "datamodel-code-generator" }, + { name = "ruff" }, +] build = [ { name = "setuptools" }, ] dev = [ + { name = "datamodel-code-generator" }, { name = "nox" }, { name = "pre-commit" }, { name = "pylint" }, @@ -751,6 +800,7 @@ dev = [ { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-vcr" }, + { name = "ruff" }, { name = "setuptools" }, ] lint = [ @@ -966,8 +1016,13 @@ requires-dist = [ provides-extras = ["cli", "doc", "openai-agents", "otel", "performance", "temporal", "all"] [package.metadata.requires-dev] +api-codegen = [ + { name = "datamodel-code-generator", specifier = "==0.72.4" }, + { name = "ruff", specifier = "==0.15.21" }, +] build = [{ name = "setuptools", specifier = ">=82.0.1" }] dev = [ + { name = "datamodel-code-generator", specifier = "==0.72.4" }, { name = "nox", specifier = "==2026.2.9" }, { name = "pre-commit", specifier = "==4.6.0" }, { name = "pylint", specifier = "==4.0.5" }, @@ -975,6 +1030,7 @@ dev = [ { name = "pytest", specifier = "==9.1.1" }, { name = "pytest-asyncio", specifier = "==1.3.0" }, { name = "pytest-vcr", specifier = "==1.0.2" }, + { name = "ruff", specifier = "==0.15.21" }, { name = "setuptools", specifier = ">=82.0.1" }, ] lint = [ @@ -1699,6 +1755,26 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c3/be/d0d44e092656fe7a06b55e6103cbce807cdbdee17884a5367c68c9860853/dataclasses_json-0.6.7-py3-none-any.whl", hash = "sha256:0dbf33f26c8d5305befd61b39d2b3414e8a407bedc2834dea9b8d642666fb40a", size = 28686, upload-time = "2024-06-09T16:20:16.715Z" }, ] +[[package]] +name = "datamodel-code-generator" +version = "0.72.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "argcomplete" }, + { name = "black", marker = "sys_platform != 'emscripten' or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-agentscope') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-agno') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-pydantic-ai-logfire') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-agno') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-pydantic-ai-logfire') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-pydantic-ai-otel-events') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-openai-agents' and extra == 'group-10-braintrust-test-strands')" }, + { name = "genson" }, + { name = "inflect" }, + { name = "isort", marker = "sys_platform != 'emscripten' or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-agentscope') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-agno') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-pydantic-ai-logfire') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-agno') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-pydantic-ai-logfire') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-pydantic-ai-otel-events') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-openai-agents' and extra == 'group-10-braintrust-test-strands')" }, + { name = "jinja2" }, + { name = "pydantic" }, + { name = "pyyaml" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-agentscope') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-agno') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-pydantic-ai-logfire') or (extra == 'group-10-braintrust-lint' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-agno') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-agentscope' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-crewai') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-agno' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-deepagents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-crewai' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-langchain') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-deepagents' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-litellm') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-langchain' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-livekit-agents') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-litellm' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-openai-agents') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-pydantic-ai-logfire') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-pydantic-ai-otel-events') or (extra == 'group-10-braintrust-test-livekit-agents' and extra == 'group-10-braintrust-test-strands') or (extra == 'group-10-braintrust-test-openai-agents' and extra == 'group-10-braintrust-test-strands')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/97/b1/a34381cab4c126623d8d59728ffcdb4cb2822877b00484189f1438eae087/datamodel_code_generator-0.72.4.tar.gz", hash = "sha256:b9f0992d46eac4664c4e0b633d93c6e384d39fa8f2df491ac79f05f72ae724fd", size = 1968256, upload-time = "2026-08-12T16:26:06.141Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/f3/d11738bc4672952b50fa0aa703cc33e17ea432482403c580c6e0d9a7b2d3/datamodel_code_generator-0.72.4-py3-none-any.whl", hash = "sha256:96cb2edbcf3b50c4cc246a48dac5cb5ff848af0675bb4e81235467c47e1038e4", size = 555785, upload-time = "2026-08-12T16:26:04.347Z" }, +] + [[package]] name = "ddtrace" version = "4.12.0" @@ -2265,6 +2341,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a8/85/527a729ecd58b7169430e47febdab2e3f91193d0e3f5a56d721c04525709/genai_prices-0.0.73-py3-none-any.whl", hash = "sha256:64dfbbf55df91db6b74ff2b24ac752b8154952e0aed4e62868d6cd42710bf742", size = 92507, upload-time = "2026-07-29T12:48:57.194Z" }, ] +[[package]] +name = "genson" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/53/de162dc8e03fccd9ebe59d17c7812378fe8bd2b604f6b1b94d00165140ac/genson-1.4.0.tar.gz", hash = "sha256:bc7f1c1bae87a21ca44d81149aec95a3f4468d676de9b8b08caa064f3c50b3da", size = 47908, upload-time = "2026-07-06T08:21:50.331Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/02/767f744ab6d4cb7761e5008acc3d534b7a0481af62563d52e391fbcb2140/genson-1.4.0-py3-none-any.whl", hash = "sha256:03bc71bbe52defde70660cc4dcd1ea1097997da5a1cbb90a9dbd3acc7c9e1b65", size = 24484, upload-time = "2026-07-06T08:21:49.046Z" }, +] + [[package]] name = "gepa" version = "0.1.1" @@ -2799,6 +2884,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, ] +[[package]] +name = "inflect" +version = "7.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, + { name = "typeguard" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/c6/943357d44a21fd995723d07ccaddd78023eace03c1846049a2645d4324a3/inflect-7.5.0.tar.gz", hash = "sha256:faf19801c3742ed5a05a8ce388e0d8fe1a07f8d095c82201eb904f5d27ad571f", size = 73751, upload-time = "2024-12-28T17:11:18.897Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/eb/427ed2b20a38a4ee29f24dbe4ae2dafab198674fe9a85e3d6adf9e5f5f41/inflect-7.5.0-py3-none-any.whl", hash = "sha256:2aea70e5e70c35d8350b8097396ec155ffd68def678c7ff97f51aa69c1d92344", size = 35197, upload-time = "2024-12-28T17:11:15.931Z" }, +] + [[package]] name = "iniconfig" version = "2.3.0" @@ -6663,6 +6761,45 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/94/d9/463feca73ec119a135d90c9f40c0172b4758150b5ed442f0ca1e8fed807a/python_socketio-5.16.4-py3-none-any.whl", hash = "sha256:0eb9c7687e7fbf59e60d714fd62afba77dfaf8ef8a06a0bff05a86c351accc2f", size = 82098, upload-time = "2026-08-06T23:11:19.851Z" }, ] +[[package]] +name = "pytokens" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b6/34/b4e015b99031667a7b960f888889c5bd34ef585c85e1cb56a594b92836ac/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a", size = 23015, upload-time = "2026-01-30T01:03:45.924Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/24/f206113e05cb8ef51b3850e7ef88f20da6f4bf932190ceb48bd3da103e10/pytokens-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a44ed93ea23415c54f3face3b65ef2b844d96aeb3455b8a69b3df6beab6acc5", size = 161522, upload-time = "2026-01-30T01:02:50.393Z" }, + { url = "https://files.pythonhosted.org/packages/d4/e9/06a6bf1b90c2ed81a9c7d2544232fe5d2891d1cd480e8a1809ca354a8eb2/pytokens-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:add8bf86b71a5d9fb5b89f023a80b791e04fba57960aa790cc6125f7f1d39dfe", size = 246945, upload-time = "2026-01-30T01:02:52.399Z" }, + { url = "https://files.pythonhosted.org/packages/69/66/f6fb1007a4c3d8b682d5d65b7c1fb33257587a5f782647091e3408abe0b8/pytokens-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:670d286910b531c7b7e3c0b453fd8156f250adb140146d234a82219459b9640c", size = 259525, upload-time = "2026-01-30T01:02:53.737Z" }, + { url = "https://files.pythonhosted.org/packages/04/92/086f89b4d622a18418bac74ab5db7f68cf0c21cf7cc92de6c7b919d76c88/pytokens-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4e691d7f5186bd2842c14813f79f8884bb03f5995f0575272009982c5ac6c0f7", size = 262693, upload-time = "2026-01-30T01:02:54.871Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7b/8b31c347cf94a3f900bdde750b2e9131575a61fdb620d3d3c75832262137/pytokens-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:27b83ad28825978742beef057bfe406ad6ed524b2d28c252c5de7b4a6dd48fa2", size = 103567, upload-time = "2026-01-30T01:02:56.414Z" }, + { url = "https://files.pythonhosted.org/packages/3d/92/790ebe03f07b57e53b10884c329b9a1a308648fc083a6d4a39a10a28c8fc/pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440", size = 160864, upload-time = "2026-01-30T01:02:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/13/25/a4f555281d975bfdd1eba731450e2fe3a95870274da73fb12c40aeae7625/pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc", size = 248565, upload-time = "2026-01-30T01:02:59.912Z" }, + { url = "https://files.pythonhosted.org/packages/17/50/bc0394b4ad5b1601be22fa43652173d47e4c9efbf0044c62e9a59b747c56/pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d", size = 260824, upload-time = "2026-01-30T01:03:01.471Z" }, + { url = "https://files.pythonhosted.org/packages/4e/54/3e04f9d92a4be4fc6c80016bc396b923d2a6933ae94b5f557c939c460ee0/pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16", size = 264075, upload-time = "2026-01-30T01:03:04.143Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1b/44b0326cb5470a4375f37988aea5d61b5cc52407143303015ebee94abfd6/pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6", size = 103323, upload-time = "2026-01-30T01:03:05.412Z" }, + { url = "https://files.pythonhosted.org/packages/41/5d/e44573011401fb82e9d51e97f1290ceb377800fb4eed650b96f4753b499c/pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083", size = 160663, upload-time = "2026-01-30T01:03:06.473Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e6/5bbc3019f8e6f21d09c41f8b8654536117e5e211a85d89212d59cbdab381/pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1", size = 255626, upload-time = "2026-01-30T01:03:08.177Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3c/2d5297d82286f6f3d92770289fd439956b201c0a4fc7e72efb9b2293758e/pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1", size = 269779, upload-time = "2026-01-30T01:03:09.756Z" }, + { url = "https://files.pythonhosted.org/packages/20/01/7436e9ad693cebda0551203e0bf28f7669976c60ad07d6402098208476de/pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9", size = 268076, upload-time = "2026-01-30T01:03:10.957Z" }, + { url = "https://files.pythonhosted.org/packages/2e/df/533c82a3c752ba13ae7ef238b7f8cdd272cf1475f03c63ac6cf3fcfb00b6/pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68", size = 103552, upload-time = "2026-01-30T01:03:12.066Z" }, + { url = "https://files.pythonhosted.org/packages/cb/dc/08b1a080372afda3cceb4f3c0a7ba2bde9d6a5241f1edb02a22a019ee147/pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b", size = 160720, upload-time = "2026-01-30T01:03:13.843Z" }, + { url = "https://files.pythonhosted.org/packages/64/0c/41ea22205da480837a700e395507e6a24425151dfb7ead73343d6e2d7ffe/pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f", size = 254204, upload-time = "2026-01-30T01:03:14.886Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d2/afe5c7f8607018beb99971489dbb846508f1b8f351fcefc225fcf4b2adc0/pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1", size = 268423, upload-time = "2026-01-30T01:03:15.936Z" }, + { url = "https://files.pythonhosted.org/packages/68/d4/00ffdbd370410c04e9591da9220a68dc1693ef7499173eb3e30d06e05ed1/pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4", size = 266859, upload-time = "2026-01-30T01:03:17.458Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c9/c3161313b4ca0c601eeefabd3d3b576edaa9afdefd32da97210700e47652/pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78", size = 103520, upload-time = "2026-01-30T01:03:18.652Z" }, + { url = "https://files.pythonhosted.org/packages/8f/a7/b470f672e6fc5fee0a01d9e75005a0e617e162381974213a945fcd274843/pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321", size = 160821, upload-time = "2026-01-30T01:03:19.684Z" }, + { url = "https://files.pythonhosted.org/packages/80/98/e83a36fe8d170c911f864bfded690d2542bfcfacb9c649d11a9e6eb9dc41/pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa", size = 254263, upload-time = "2026-01-30T01:03:20.834Z" }, + { url = "https://files.pythonhosted.org/packages/0f/95/70d7041273890f9f97a24234c00b746e8da86df462620194cef1d411ddeb/pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d", size = 268071, upload-time = "2026-01-30T01:03:21.888Z" }, + { url = "https://files.pythonhosted.org/packages/da/79/76e6d09ae19c99404656d7db9c35dfd20f2086f3eb6ecb496b5b31163bad/pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324", size = 271716, upload-time = "2026-01-30T01:03:23.633Z" }, + { url = "https://files.pythonhosted.org/packages/79/37/482e55fa1602e0a7ff012661d8c946bafdc05e480ea5a32f4f7e336d4aa9/pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9", size = 104539, upload-time = "2026-01-30T01:03:24.788Z" }, + { url = "https://files.pythonhosted.org/packages/30/e8/20e7db907c23f3d63b0be3b8a4fd1927f6da2395f5bcc7f72242bb963dfe/pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb", size = 168474, upload-time = "2026-01-30T01:03:26.428Z" }, + { url = "https://files.pythonhosted.org/packages/d6/81/88a95ee9fafdd8f5f3452107748fd04c24930d500b9aba9738f3ade642cc/pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3", size = 290473, upload-time = "2026-01-30T01:03:27.415Z" }, + { url = "https://files.pythonhosted.org/packages/cf/35/3aa899645e29b6375b4aed9f8d21df219e7c958c4c186b465e42ee0a06bf/pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975", size = 303485, upload-time = "2026-01-30T01:03:28.558Z" }, + { url = "https://files.pythonhosted.org/packages/52/a0/07907b6ff512674d9b201859f7d212298c44933633c946703a20c25e9d81/pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a", size = 306698, upload-time = "2026-01-30T01:03:29.653Z" }, + { url = "https://files.pythonhosted.org/packages/39/2a/cbbf9250020a4a8dd53ba83a46c097b69e5eb49dd14e708f496f548c6612/pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918", size = 116287, upload-time = "2026-01-30T01:03:30.912Z" }, + { url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" }, +] + [[package]] name = "pywin32" version = "312" @@ -7242,6 +7379,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/10/85/48f0abdcef5cce4e034c7a5b0ceeceba0b01bf0d942824f4bb720afe2dec/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826", size = 586486, upload-time = "2026-06-30T07:17:51.141Z" }, ] +[[package]] +name = "ruff" +version = "0.15.21" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" }, + { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" }, + { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" }, + { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" }, + { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" }, + { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" }, + { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" }, + { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" }, + { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" }, + { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" }, + { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" }, + { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" }, + { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" }, + { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" }, + { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" }, +] + [[package]] name = "s3transfer" version = "0.19.2" @@ -7837,6 +7999,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/19/97/56608b2249fe206a67cd573bc93cd9896e1efb9e98bce9c163bcdc704b88/truststore-0.10.4-py3-none-any.whl", hash = "sha256:adaeaecf1cbb5f4de3b1959b42d41f6fab57b2b1666adb59e89cb0b53361d981", size = 18660, upload-time = "2025-08-12T18:49:01.46Z" }, ] +[[package]] +name = "typeguard" +version = "4.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b4/de/4420db493fa8fc0856d5e5c1b159c63a323d2de2317babe36b01568928e8/typeguard-4.6.0.tar.gz", hash = "sha256:e7414f09111317de3e335de92cd397c5c0ca00b1cc1676de12e1d444a79b3f21", size = 82330, upload-time = "2026-07-26T08:40:23.207Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/eb/461d5f167b6f5c7d97696f397c82f82e3480e003fce3f0a1cd1dd26e2eb2/typeguard-4.6.0-py3-none-any.whl", hash = "sha256:79878165bb86f2cf5d41d159a0ff1792a796cf496882d2fe1b1c6c7049b9cdd7", size = 36884, upload-time = "2026-07-26T08:40:21.868Z" }, +] + [[package]] name = "typer" version = "0.27.1" diff --git a/pyproject.toml b/pyproject.toml index b7d159c8..3f4653bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,6 +4,7 @@ force-exclude = true extend-exclude = [ "py/src/braintrust/_generated_types.py", "py/src/braintrust/generated_types.py", + "py/src/braintrust/api/_generated/", ] [tool.ruff.lint]