Evaluators
Evaluators return typed assessments independently of chat models and tool-approval
policies. Callers decide what a probability, choice, or score means for their use
case.
Resolve a latest.EvaluatorConfig against the configured providers, then construct
one reusable client per team:
resolved, err := cfg.Resolve(providers)
if err != nil {
return err
}
client, err := provider.New(ctx, resolved, env)
if err != nil {
return err
}
result, err := client.Evaluate(ctx, map[string]any{"message": message})
Evaluate accepts a string, JSON object, or JSON array. Null, numeric, boolean,
and non-JSON-serializable states are rejected before credentials are requested.
State is sent to the configured evaluator service; callers must select the data
appropriate for that service.
TypeSafe
The initial backend posts one question named evaluation to /v1/systemone.
It requires an explicit model, uses https://api.typesafe.ai by default, and
retrieves TYPESAFE_API_KEY from the environment provider on each request. A
custom token key, base URL, exact endpoint, and timeout can be configured.
endpoint overrides the base URL and uses its path unchanged, allowing
Jev-compatible services such as Laya on Baseten's /development/predict.
Credentials, queries, and fragments are rejected in both URL settings. Automatic
TypeSafe pricing applies only when the effective endpoint is the official URL.
The default timeout
is 10 seconds and includes credential lookup, HTTP transfer, and response reads.
Requests respect context cancellation. Redirects are never followed, responses
are limited to 1 MiB, and errors omit credentials, input, and response bodies.
Requests are not automatically retried.
| Config type |
TypeSafe question |
Criteria |
Result |
boolean |
noul |
None |
Probability in [0, 1] |
choice |
choice |
Choices, a key-to-description map |
Choice and Probabilities |
score |
score |
Levels, ordered descriptions |
Score and Probabilities |
Scores use zero-based level indices, with probability keys "0", "1", etc.
Probability maps must have exactly the configured keys and sum to one within
0.001. A selected choice must have a highest probability; ties are accepted.
Scores must lie between zero and the final level index, allowing 0.001 for
rounding. Returned values are not normalized or clamped.
Result.Model identifies the model returned by the service. Result.Usage
contains input and output token counts. Zero-valued probabilities, scores, and
confidence remain present through pointer fields. Missing or null confidence
stays nil; required probabilities and scores cannot be missing or null.
Usage observation and pricing
Result.Cost is an estimated USD charge, with nil indicating unknown usage or
pricing and non-nil zero indicating a known zero charge. Automatic pricing is
limited to the official endpoint and returned model ID jev-1.13.0:
$0.042/M input tokens, output free. Aliases and
future versions are not guessed. Set EvaluatorConfig.Cost to override pricing,
including for custom endpoints; an empty cost object explicitly means free.
Overrides are copied when constructing the client. Cache prices are unused.
Observe request accounting independently of answer validity:
ctx = evaluator.WithUsageObserver(ctx, func(record evaluator.UsageRecord) {
// Record known tokens/cost or track unknown usage/pricing separately.
account(record)
})
result, err := client.Evaluate(ctx, state)
The callback runs synchronously once per attempted HTTP request, even for errors
or invalid answers. Transport failures report unknown usage; local validation and
credential failures before a request produce no record.
UsageRecord.Model is the returned model ID, falling back to the requested ID.
UsageRecord.Usage is nil for missing, null, incomplete, or malformed counts;
explicit zero counts are non-nil. Unreadable or malformed responses report unknown
usage. Result.Usage remains a value for compatibility. The observer receives
independent copies of usage and cost; it cannot change the returned result.
Observers are context-scoped, not retained by clients. A new observer replaces
an inherited one; nil disables it. Shared callbacks must synchronize their state,
and all callbacks must finish before Evaluate returns. Report every attempted
request separately, including requests made by custom retrying evaluators.
Count records once, not again from results. The runtime uses these estimates for
session totals and budget accounting but are not invoices; unknown values should
not be treated as free.
Run local tests with go test -race ./pkg/evaluator/.... Tests use fake
environment providers and local HTTP servers, not the TypeSafe API.