Skip to content

FEAT: Add a general scorer registry API for dataset-driven scenarios #2970

Description

@romanlutz

Is your feature request related to a problem? Please describe.

The dataset explorer in #2744 needs to discover and select configured scorer instances for its custom-scenario flow, rather than hardcoding scorer classes or accepting serialized Python components from the browser. ScorerRegistry already discovers types, exposes constructor metadata, resolves component references, constructs instances, and holds named configured instances. This issue captured the missing general HTTP contract over that registry.

#2834 attempted a specialized objective-presets API for #2755 and closed without merging after Rich's review requested a general registry API first. The subsequent proposal here helped define the backend boundary.

Completed by #2990, merged on October 5, 2026. Rich's final direction on #2755 settled the contract, and #2755 was revised to cover the same general backend scope. This related issue does not represent a second implementation or an additional child in the 17-item dataset roadmap. The earlier contract hold and flat-summary proposal below are superseded by the implemented decision recorded here.

Describe the solution you'd like

Implemented general API

#2990 adds thin typed routes and a service over the existing ScorerRegistry:

Route Purpose
GET /api/scorers/types List scorer types with shared constructor-parameter metadata.
GET /api/scorers List named, configured instances with bounded pagination.
GET /api/scorers/{scorer_registry_name} Retrieve one configured instance by registry name.
POST /api/scorers Construct and register a named instance through the shared registry/resolver, returning the same instance model.

The final typed contracts are:

  • ScorerTypeEntry: scorer_type, shared parameters: list[Parameter], is_llm_based, and description; type discovery uses an items envelope.
  • ScorerInstance: scorer_registry_name, full typed identifier: ScorerIdentifier, and description; list responses use items and the existing pagination model.
  • CreateScorerRequest: required name and type, plus params defaulting to an empty object when omitted, using shared registry construction and named component references.

Contract decision: return the full ScorerIdentifier, including child scorers and target identifiers. This deliberately replaces the earlier proposed flat allowlist and blanket prohibition on nested identifiers. Credential values must still be excluded. Identifiers can contain non-secret configuration; they are not a substitute for registry tags, compatible-default selection, or objective-suitability policy.

Keep buildable types distinct from configured instances. A type appearing in the catalog does not prove that its dependencies are initialized or that it is a suitable objective scorer.

Behavior and boundaries

  • The core registry and shared resolver own constructor metadata, reference resolution, scorer-specific parameter checks, and construction. The backend handles HTTP validation and error translation, not a second registry or a parallel introspection/compatibility implementation.
  • List/detail/type reads do not construct scorers, score content, call targets, fetch datasets, or generate conversations. Creation configures an instance; it is not a scoring operation.
  • Failed creation must not register a partial instance. Duplicate-name creation must not silently replace an existing one, including concurrent requests.
  • The implementation paginates configured instances in sorted registry-name order. An unknown cursor currently restarts at the first page, following the existing target-service convention; the earlier proposal to return 400 for this case was not the behavior shipped in FEAT: expose ScorerRegistry through the backend API #2990.
  • Registry names identify configured instances in the current runtime. They are not persistent saved configurations and may disappear after registry reset/reinitialization or restart. The service cache is reset when runtime registries are replaced.
  • Reuse backend-configured dependencies and existing authentication conventions. This work adds no browser credential-entry flow, credential store, memory schema migration, persistent scorer store, or execution engine.

Acceptance criteria completed in #2990:

  • Typed request/response contracts distinguish type discovery from configured-instance discovery.
  • List, detail, and create use one shared instance model with full nested identifiers.
  • Named creation uses the shared resolver and the created instance is retrievable by registry name.
  • Pagination, invalid construction input/references, duplicate names, failed construction, and registry lifecycle changes have focused route/service coverage.
  • Read endpoints do not construct or invoke scorers, targets, or dataset providers.
  • Local fake-registry tests cover nested scorer/target identifiers, credential exclusion, and concurrent duplicate creation without paid calls.
  • Existing /scores operations remain separate; no dataset-specific objective-selection or scenario-default policy is added by these routes.

Remaining dataset-explorer consumers

Basic cards, browsing, media previews, and single-example chat imports do not depend on this API. The dependent flow is selected examples -> Configure scenario -> preview/estimate -> confirmed launch.

The requirements not implemented by #2990 are now explicit in the existing roadmap:

These are retained follow-ups, not acceptance criteria falsely marked complete here. #2757 still waits for #2756 and maintainer promotion; completing #2755/#2990 does not bypass the main explorer/provider-loading sequence.

Describe alternatives you've considered, if relevant

  • A specialized /objective-presets endpoint first would establish the separate contract that prompted [FEAT] Expose configured objective-scorer presets #2834's closure.
  • A flat instance summary was proposed here, but the final maintainer decision chose full typed identifiers, matching the shared catalog approach. The original comment thread remains as decision history.
  • A hardcoded GUI list would miss initializer-provided instances and custom/composite scorers.
  • A new general scorer-builder GUI, scorer execution endpoint, arbitrary Python/import support, or update/delete API is outside this completed backend slice.

Additional context

Implementation: #2990, merge commit 5f619c0b87e342ba15b5dd0af29df4858ecce5e9. Related completed roadmap milestone: #2755. The contributor confirmed the general-backend scope and left objective presets and the GUI as follow-ups in this comment.

Rich's broader scorer contract proposal and phase-8 #2899 concern Python evidence/expectation/scorer contracts, not this HTTP endpoint specification. They are related SDK work, not a separate unimplemented copy of the API now shipped in #2990.

Starting points: pyrit\registry\components\scorer_registry.py, pyrit\backend\models\scorers.py, pyrit\backend\services\scorer_service.py, pyrit\models\catalog\scorer.py, ScorerInitializer, ScenarioConfigurationResolver, and Scenario._get_default_objective_scorer().

Follow doc\code\framework.md: registries build and hold components, the backend exposes HTTP contracts, scenarios package selected components, scorers evaluate evidence, and attacks act on scores.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    GUIUmbrella label for all feedback submitted via the Co-PyRIT GUIfeature-request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions