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:- 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_endedevent. - 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. - For each
RemoteScoreron a matching signal, the worker builds aschema_version: 2request from the turn’s span, including its messages, resolves the scorer’s credentials, checks the endpoint URL against the allowed hosts, and sends thePOST. - The worker validates the response and writes the result as feedback on the turn. Tags and ratings appear on the Signals tab.
Monitor whose op_names is ["weave.genai.turn_ended"], whether you create it in the UI or with the SDK.
The worker retries a failed attempt with the same Idempotency-Key, up to three attempts within 30 seconds of the first attempt. A 5xx, 408, or 429 response is retried. A timeout uses the whole 30 seconds, so a timed-out request isn’t retried. Any other 4xx response isn’t retried. If your endpoint can’t score a turn in time, return 503 quickly rather than letting the request time out, so that Weave retries it. 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 To enable remote scorers for an organization, an organization or billing admin must:- Open
https://wandb.ai/account-settings/[ORG]/settings, replacing[ORG]with the organization that owns your project. - Select the Remote scoring tab.
- Turn on Enable remote scoring.
- 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.
- Click Save settings.
extraEnv on each scoring worker: the online evaluation worker, the call scoring worker, and the agent scoring worker.
To show the remote scoring settings and scorer options in the Weave UI, also set
GORILLA_GATE_WEAVE_REMOTE_SCORING=true on the W&B server.
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.commatchesa.corp.example.comanda.b.corp.example.com, notcorp.example.com. The suffix after*.must contain at least two labels, so*.comis 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. On Self-Managed, private addresses in the networks listed in
WF_SCORING_WORKER_REMOTE_SCORER_ALLOWED_PRIVATE_CIDRSare allowed. - HTTPS is required unless the deployment permits insecure HTTP.
- Redirects aren’t followed.
Build the scorer endpoint
Your endpoint accepts a JSONPOST from Weave and returns a JSON score. For a reference implementation, see Sample code.
Request
Weave sends one HTTPPOST per scored target to the scorer’s endpoint URL, with these headers:
Weave might deliver the same scoring attempt more than once. Use
Idempotency-Key to deduplicate if needed for your endpoint. 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.
An agent turn request carries two version numbers. The top-level schema_version is the envelope version, which is 2 for agent turns. The scored data is under scoring_target, a tagged union with three fields:
type: The kind of target.agent_turnfor a turn. The contract also definescall, which agent turn scoring never sends.schema_version: The payload version for that type. It counts independently of the envelope version. Theagent_turnpayload is at payload version1.payload: The data for that type.
scoring_target.type together with scoring_target.schema_version to choose how to score the payload. Return 4xx for a combination your endpoint doesn’t handle, such as call if you score only agent turns.
The agent_turn payload at payload 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.
1.
Response
Return HTTP200 with a JSON object that has two fields:
schema_version: Integer equal to the request’sschema_version.result: One score object, a list of score objects, or an object of the form{"scores": [...]}.
Weave treats any non-
200 response as a scorer failure and records no feedback for that attempt. Weave doesn’t follow redirects and treats them as failures. 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. The following example returns one score object:
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. EachRemoteScorer 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.
Create a remote scorer signal
Create the signal in the Weave UI or with the Python SDK. Both create aRemoteScorer attached to a monitor that targets weave.genai.turn_ended.
Weave UI
Create the signal from the Agents view:- In the Weave project sidebar, click Agents.
- In the tab bar, click Signals.
- Click New signal, then click Remote scorer.
- 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
POSTto. - 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
ANDlogic. - Sample rate (Optional): Expand Advanced, then set the fraction of matching turns the signal scores.
- Click Create signal.
Python SDK
Publish aRemoteScorer, then activate a Monitor that lists it in scorers and targets weave.genai.turn_ended in op_names.
OAuthClientCredentialsConfig as auth_config instead.
Sample code
Theexamples/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:
remote_scorer_app.py: A FastAPI app withGET /healthandPOST /score.auth.py: A development-only bearer token check against theREMOTE_SCORER_DEV_BEARER_TOKENenvironment variable.scoring_logic.py: Unwraps either envelope withextract_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 aRemoteScorerand activates a monitor for completed agent turns.trigger_test_agent_turn.py: Logs one turn withweave.conversation.log_turn.
0.53.0 or later. A local run verifies only the contract.
Test the signal
Before you test, deploy the endpoint at an HTTPS URL that’s on the allowed hosts, and register it. Log one completed turn, then check the Signals tab. Scoring is asynchronous, so the result appears after a delay.scoring_target.type set to agent_turn, and Weave records the result as feedback on that turn.