Skip to main content
A remote scorer signal scores each completed agent turn with an HTTP endpoint that you host, instead of with an LLM judge. When a turn ends, the W&B Weave agent scoring worker sends the turn to your endpoint in an HTTP POST and records the response as feedback on the turn. The result appears as a tag or rating on the Signals tab of the Agents view. This page covers remote scorers for agent turns. To score calls traced with @weave.op, see Score calls with remote scorers. You configure remote scorers with the Python SDK or the Weave UI. The TypeScript SDK doesn’t include RemoteScorer.

How agent turn scoring works

An agent turn is scored in the following sequence:
  1. A turn ends. When a root span (a span with no parent) ends, Weave treats it as a completed turn and emits a weave.genai.turn_ended event.
  2. The agent scoring worker loads the project’s active signals that target weave.genai.turn_ended, then applies each signal’s filters and sample rate.
  3. For each RemoteScorer on a matching signal, the worker builds a schema_version: 2 request from the turn’s span, including its messages, resolves the scorer’s credentials, checks the endpoint URL against the allowed hosts, and sends the POST.
  4. The worker validates the response and writes the result as feedback on the turn. Tags and ratings appear on the Signals tab.
Weave scores only completed turns. Individual LLM and tool spans, and whole conversations, aren’t remote scoring targets. A remote scorer signal is a Monitor whose op_names is ["weave.genai.turn_ended"], whether you create it in the UI or with the SDK. If the endpoint returns 5xx, 408, or 429, or the request times out, the worker sends the request again with the same Idempotency-Key, up to three attempts within about 30 seconds. Any other 4xx response isn’t retried. Agent turn scoring requires the structured result format, because Weave stores the tags and ratings as typed feedback columns.

Enable remote scoring

Remote scoring is off until it’s enabled for your organization or deployment, and the scoring worker calls a scorer endpoint only if its host is on an allowlist. How you enable it depends on your deployment type. Multi-tenant Cloud An organization admin or billing admin enables remote scoring for the organization:
  1. Open https://wandb.ai/account-settings/[ORG]/settings, replacing [ORG] with the organization that owns your project.
  2. Select the Remote scoring tab.
  3. Turn on Enable remote scoring.
  4. Under Allowed hosts, click Add host and enter each host that remote scorers may call. Saving with remote scoring enabled requires at least one host. Leave the port blank to allow any port on that host.
  5. Click Save settings.
Dedicated Cloud Ask W&B to enable remote scoring for your deployment and configure its allowed hosts. Self-Managed If you run W&B Weave in a W&B Self-Managed deployment, set these values on the Weave trace server Helm chart under weave_workers.remoteScoring. The chart renders them as environment variables on each worker that can call a remote scorer: the online evaluation worker, the call scoring worker, and the agent scoring worker. Allowed host rules The scoring worker checks every scorer endpoint URL, and separately the OAuth token endpoint URL when a scorer uses OAuth, against these rules:
  • An entry matches an exact host, with an optional port. An entry without a port allows any port on that host.
  • An entry that starts with *. matches subdomains at any depth, but not the domain itself. *.corp.example.com matches a.corp.example.com and a.b.corp.example.com, not corp.example.com. The suffix after *. must contain at least two labels, so *.com is rejected. A wildcard can’t be combined with an IP address.
  • When both an operator allowlist and an organization allowlist exist, the URL must satisfy both. An empty operator allowlist adds no restriction. When no allowlist exists at all, the worker rejects every host.
  • Loopback, private, internal, and cloud metadata addresses are rejected.
  • HTTPS is required unless the deployment permits insecure HTTP.
  • Redirects aren’t followed.

Build the scorer endpoint

Your endpoint accepts a JSON POST from Weave and returns a JSON score.

Request

Weave sends one HTTP POST per scored target to the scorer’s endpoint URL, with these headers: Weave might deliver the same scoring attempt more than once. If your endpoint has side effects, use Idempotency-Key to deduplicate. The key is stable for one request version, so a V1 and a V2 request for the same call carry different keys. Every request body has these top-level fields: Weave omits an optional field with no value rather than sending it as null. Weave might add optional fields to a version without changing its number, so ignore fields you don’t recognize. Request and response bodies are limited to 1 MiB each and contain JSON text only, never images, audio, or video. A target that exceeds these limits isn’t sent, so it isn’t scored. Each request carries one target. For an agent turn, schema_version is 2 and the scored data is under scoring_target, a tagged union with three fields:
  • type: The kind of target. agent_turn for a turn, or call for a traced call.
  • schema_version: The version of the payload for that type, independent of the top-level version.
  • payload: The data for that type.
Dispatch on the top-level schema_version first, then on the pair of scoring_target.type and scoring_target.schema_version. Return 4xx for a pair your endpoint doesn’t implement. The call payload at version 1 is the same object that a V1 request sends as original_call, so one endpoint can accept both by unwrapping the envelope first. Call monitors send V1. The agent_turn payload at version 1 has these fields: A turn that ends without an explicit status arrives with status.code set to UNSET. Treat UNSET as a normal completed turn and ERROR as the failure signal. Each message in input and output has role, content, and finish_reason. content is plain text, or a JSON-encoded array of parts when the message carries structured content such as tool calls.
Weave adds optional fields to a payload without changing its version. Weave removes, renames, or changes the meaning of a field only with a new scoring_target.schema_version for that type, or a new top-level schema_version for changes to the envelope. A new target type joins the V2 union at inner version 1.

Response

Return HTTP 200 with a JSON object that has two fields:
  • schema_version: Integer equal to the request’s schema_version.
  • result: One score object, a list of score objects, or an object of the form {"scores": [...]}.
A score object has these fields: Weave treats any non-200 response as a scorer failure and records no feedback for that attempt. Weave doesn’t follow redirects, so a redirect is also a failure. Weave doesn’t parse the body of an error response. Return 4xx for requests your endpoint never accepts and 5xx for temporary problems. For an agent turn request, the response’s schema_version is 2, and result must use one of the three structured shapes:

Authenticate requests from Weave

Weave authenticates to your endpoint with a bearer token. The request carries no W&B credential. The token proves to your endpoint that the request came from Weave, not the reverse. Each RemoteScorer uses one of two modes: Store the client secret or bearer token in the secret store of the team that owns the project before you register the scorer. The RemoteScorer configuration holds only the secret name. The scoring worker resolves the value at scoring time. The Weave UI also offers Deployment default, which stores no authentication configuration for the scorer and relies on a fallback credential set by the deployment operator. Multi-tenant Cloud sets no fallback credential. Use one of the two explicit modes.

Create a remote scorer signal

Create the signal in the Weave UI or with the Python SDK. Both create a RemoteScorer attached to a monitor that targets weave.genai.turn_ended.

Weave UI

Create the signal from the Agents view:
  1. In the Weave project sidebar, click Agents.
  2. In the tab bar, click Signals.
  3. Click New signal, then click Remote scorer. If the project has no inference provider and no signals yet, click Use a remote scorer instead.
  4. In the Remote scorer drawer, Scored by is set to Remote scorer. Configure the following fields:
    • Scorer name: The name shown in the Scorer column of the Signals table. Up to 128 characters.
    • Scoring endpoint URL: The URL Weave sends the POST to.
    • Authentication: Static bearer or OAuth client credentials. For static bearer, select or enter the Bearer token secret name. For OAuth, enter the Token endpoint URL, Client ID, Client secret name, and optional Scope. Secret fields take team secret names, not values.
    • Config (JSON, optional): A JSON object passed to your endpoint as scorer.config.
    • Only score turns matching (Optional): Expand Advanced, then add filters to restrict which turns the signal scores, for example by agent name, agent version, operation name, tool name, or status code. To score every turn, leave it empty. Weave combines multiple filters with AND logic.
    • Sample rate (Optional): Expand Advanced, then set the fraction of matching turns the signal scores.
  5. Click Create signal.
The remote scorer form has no tag or rating fields. Your endpoint determines what it returns, and the Signals table shows the tags and ratings it receives. In the Scorer column, a remote scorer signal shows a webhook icon.

Python SDK

Publish a RemoteScorer, then activate a Monitor that lists it in scorers and targets weave.genai.turn_ended in op_names.
For OAuth client credentials, pass an OAuthClientCredentialsConfig as auth_config instead. For both authentication classes, see Register a remote scorer.

Test the signal

Log one completed turn, then check the Signals tab. Scoring is asynchronous, so the result appears after a delay.
Your endpoint receives a V2 request with scoring_target.type set to agent_turn, and Weave records the result as feedback on that turn.

Troubleshooting

Sample code

The examples/remote_scorer directory in the weave repository is the reference implementation of this contract and the source of truth for the sample code. One endpoint in that sample accepts V1 call requests, V2 call requests, and V2 agent turn requests. For agent turns, these files apply:
  • scoring_logic.py: Unwraps either envelope with extract_scoring_target, then scores the turn’s last output message.
  • sample_request_v2_agent_turn.json: A complete V2 agent turn request.
  • register_remote_scorer.py --agent-turn: Publishes a RemoteScorer and activates a monitor for completed agent turns.
  • trigger_test_agent_turn.py: Logs one turn with weave.conversation.log_turn.
To run the endpoint locally and send it a V2 agent turn request without Weave, start the app, then send the sample request:
The sample requires Weave 0.53.0 or later. A local run verifies only the contract. To test with Weave, deploy the endpoint at an HTTPS URL on the allowed hosts and register it as described in Create a remote scorer signal.