Use decision models
Register Jev, Laya, or Clef and request choices, rubric scores, yes/no judgments, and image boxes.
Decision models return structured judgments. GoodMem supports Jev, Laya, and Clef through one registration and decision API. They are separate resources from LLMs, embedders, and rerankers.
Register an endpoint
Start with a running provider and its model identifier: Jev, Laya, or Clef. Registration connects GoodMem to that deployment; it does not download or start a model.
With the CLI configured for your GoodMem server and API key, register a Laya endpoint:
goodmem decision-model create --display-name "Support decisions" \
--provider laya --endpoint-url http://your-laya-host:8000 \
--model your-deployed-checkpoint --configuration '{"timeout_millis":30000}'Create, get, and update print JSON. Copy decisionModelID from the CLI response and use it as
MODEL_ID below. REST responses use decisionModelId instead.
For REST, send your GoodMem key in the x-api-key header. Create a registration with
POST /v1/decision-models; for a Laya deployment, the JSON body looks like:
{
"displayName": "Support decisions",
"providerType": "LAYA",
"endpointUrl": "http://your-laya-host:8000",
"apiPath": "/v1/systemone",
"modelIdentifier": "your-deployed-checkpoint",
"configuration": {"timeout_millis": 30000}
}Use the endpoint and model identifier from your deployment. Jev and Laya default to
/v1/systemone when apiPath is omitted. Clef requires its explicit Cloudflare account/model path.
Jev and Clef require an inline API key in credentials; Laya may be anonymous:
{"kind":"CREDENTIAL_KIND_API_KEY","apiKey":{"inlineSecret":"YOUR_PROVIDER_KEY"}}These providers use Authorization: Bearer .... Omit headerName and prefix to use those
defaults; explicitly supplying the same values is also accepted. Custom headers and schemes are not supported.
The registration can also include labels, version (up to 64 characters), and monitoringEndpoint. The monitoring URL
is stored metadata; it does not schedule checks. Duplicate connections are allowed. Configuration
supports timeout_millis, max_response_bytes, and Jev-only image_preview. Capabilities come from
GoodMem's built-in provider profiles and cannot be overridden in configuration.
Test the connection
Run a single probe against a registered model:
goodmem decision-model ping MODEL_ID --onceFor repeated probes and a latency summary, use:
goodmem ping decision-model MODEL_ID --count 5Each probe sends a small yes/no question to the registered inference endpoint and may incur
provider charges. A valid answer means the probe succeeded, whether the answer is yes or no.
Ping requires READ_DECISION_MODEL, PING_DECISION_MODEL, and EXECUTE_DECISION_MODEL authority.
The monitoring URL is not used.
The existing REST endpoint POST /v1/ping:once accepts
{"targetId":"MODEL_ID","targetTypeHint":"DECISION_MODEL"}. Use --timeout in the CLI or
timeoutMs in REST to set the per-probe timeout; the model's configured timeout still applies
when it is shorter.
Request decisions
Call DecisionModelService.Decide(DecisionRequest) over gRPC, or send
POST /v1/decision-models/{id}/decide with a shared state and named questions:
{
"state": {"text": "Please call me immediately."},
"questions": {
"urgent": {
"instructions": {"text": "Does this message need an urgent response?"},
"noul": {}
}
}
}noul returns a probability of true. choice selects an option and returns its distribution.
score returns the expected zero-based rubric index. box returns normalized image edges and
does not establish whether the target exists. Confidence is provider-specific; it is not a shared
probability of correctness.
To ask choice or score questions, add entries such as these to questions:
{
"team": {"choice": {"options": {
"billing": {"text": "Billing question"},
"support": {"text": "Technical problem"}
}}},
"priority": {"score": {"levels": [
{"text": "Routine"}, {"text": "Needs attention"}, {"text": "Urgent"}
]}}
}Content accepts ordinary text, precise JSON in a jsonValue string, recursive objects/arrays,
and embedded base64 media. Each content value uses one of these wrappers. For example, structured
state can be {"jsonValue":"{\"status\":\"open\",\"priority\":3}"}. Use objectValue.fields
or arrayValue.values when nesting content that includes images.
Consult the registration's capabilities before submitting media or
question types. Jev images require preview opt-in; Laya is text/JSON only; Clef media support depends
on the model. Providers may truncate inputs as described in their capability profiles. See the
request and capability schemas for all fields.
The CLI exposes the same operations under goodmem decision-model. Save the request body to
questions.json, then run:
goodmem decision-model decide MODEL_ID --input questions.jsonUse --input - to read from standard input. The model ID is supplied separately from the JSON body.
See the CLI reference for every command,
the REST reference for HTTP fields and filters,
or the Python SDK reference for typed calls.
Native gRPC clients
Send your GoodMem key as x-api-key metadata, without a Bearer prefix. The provider's key
belongs in the registration's credentials instead.
Use google.protobuf.Struct for configuration: bool_value for image_preview and
number_value for the bounded integer settings. Decision content uses DecisionContent:
text for ordinary text, json_value for JSON that preserves exact numbers, and recursive
objects/arrays for mixed content. Struct stores numbers as doubles, so it is not used for
decision content.
Set DecisionMedia.data to the raw file bytes in a protobuf client. Base64 encoding is for
REST/ProtoJSON representations, not native gRPC bytes fields.
Images with Jev
Set the registration's configuration to {"image_preview":true} to enable images.
For the box question below, also select modelIdentifier: "jev-preview". Check Jev's model list
and image requirements. Images and boxes are preview features.
Send a PNG or JPEG with each side between 280 and 1568 pixels. Replace BASE64_IMAGE_BYTES
with the file's base64 encoding, without a data: prefix, and submit this through Decide:
{
"state": {"text": "Inspect the attached image."},
"attachments": [
{"kind": "IMAGE", "mimeType": "image/png", "data": "BASE64_IMAGE_BYTES"}
],
"questions": {
"present": {"instructions": {"text": "Is there a red shape?"}, "noul": {}},
"location": {"instructions": {"text": "Locate the red shape."}, "box": {}}
}
}In Python, encode the file before assigning the media's data field:
import base64
from pathlib import Path
image_data = base64.b64encode(Path("image.png").read_bytes()).decode("ascii")
media = {"kind": "IMAGE", "mimeType": "image/png", "data": image_data}Access and updates
Decide requires both read and execute permission. Ordinary resource reads omit credentials;
explicit credential reads require separate authority. Lists require collection list permission and
return only readable registrations. Use pageSize and pass nextPageToken back as pageToken.
Update a registration with PUT /v1/decision-models/{id}. Omitted fields stay unchanged; an empty
monitoringEndpoint clears it. A supplied configuration replaces the entire configuration object;
include any settings you want to retain, or send {} to restore defaults. Provider and owner cannot
be changed. Deleting a registration does not delete the upstream model.
goodmem decision-model get MODEL_ID # includes capabilities
goodmem decision-model update MODEL_ID --display-name "Support triage"
goodmem decision-model delete MODEL_IDDecide does not persist inputs or answers. With tracing enabled, its gen_ai.decide span shows
the model, duration, outcome and provider-reported token counts. Telemetry excludes state,
question names, rubrics, media and answers. See the tracing reference
for export mappings and usage limits. Calls are not
automatically retried; an ambiguous failure may still have incurred provider charges. For native
provider requests, use /v1/proxy/decision-models/{id}/..., which additionally requires proxy
permission. With no trailing path, the proxy uses the registered apiPath.