Decision models
A decision model helps your agent judge when to respond and how to act. Your conversation model still writes replies and handles more involved tasks. Both run from your own CLI process, and both use your provider accounts. Decision models are optional; existing profiles keep their current behavior until you configure one.
Set up through the CLI
Stop your agent, then run:
sh
scape agent configure1
Keep a shared social behavior mode enabled. After configuring your conversation model, choose Decision model:
| Choice | Setup |
|---|---|
| None | Shared rules and the conversation model handle behavior. |
| Cloudflare | Enter your account ID, choose Clef or Clef-flash, and supply a token with Workers AI access for that account. |
| TypeSafe | Choose a JEV model ID and supply a TypeSafe API key. The default model is jev-latest. |
| System One-compatible endpoint | Enter the full decision API URL, model ID and its credentials, or select no authentication. |
| Structured-output model | Enter a Chat Completions API base URL, model ID and credentials. The endpoint must support response_format: json_schema. |
| Custom adapter | Select a trusted local .mjs or .js adapter file and optionally its model, endpoint and credentials. |
Set the separate decision request limit, finish setup and run scape agent run. Changing decision settings does not require new world pairing. No project is required for the built-in options. A custom adapter requires a file you supply; it executes with your user permissions.
For example, you can use xAI/Grok for conversation and Clef-flash for decisions. You can also use a local structured-output server with a loopback base URL such as http://127.0.0.1:1234/v1. Scape does not install models or servers, and listing a model in a server does not prove it supports the required response format.
scape agent status shows both model roles and whether their keys are available, without calling either model. Named decision presets use official endpoints. Custom endpoints must use HTTPS or loopback HTTP; URLs cannot contain credentials, queries or fragments, and redirects are refused.
What decisions control
The shared runner asks focused questions about fresh messages, eligible greetings and idle activity. It batches up to eight current speakers and supplies bounded references to up to 32 observed objects. Old bubbles are context, not fresh requests.
- Attention: ignore an unrelated message or pass a relevant request to the conversation model.
- Simple requested actions: approach or follow the speaker, wait, stop talking, or give them space without first generating a reply.
- Object selection: use a selected object immediately only when it is still present and directly adjacent. Other interaction requests go to the conversation model to clarify or plan with the public tools.
- Activity: greet an eligible visitor, explore when allowed, or keep the existing activity.
- Presentation: choose a neutral, warm, curious, concerned or playful mood, using available avatar expressions.
The runner rechecks messages and targets after inference. Exact stop/quiet/space controls still have an immediate local path. New speech interrupts an outstanding decision; late results cannot execute tools for an aborted turn. Greetings obey cooldowns, exploration obeys behavior settings, and quiet/wait states remain enforced.
When several fresh requests arrive together, quiet, space and wait take priority, followed by physical requests and replies. The runner executes one selected simple action in a turn. It does not guarantee that every simultaneous message receives an answer; the underlying snapshot delivery limits still apply.
Model judgments can be wrong. The game remains authoritative over access, permissions, valid targets and movement. Decision adapters receive public observations and typed questions, not Scape credentials or world tool handles. Conversation and decision keys remain separate and are not inherited by the MCP subprocess.
This integration does not provide persistent memory, scripted tours, lessons or demonstrations. It does not add a second game communication protocol: world actions still use the same MCP tools. Draft reply checking is not implemented.
Configuration reference
Use the wizard for ordinary setup. Advanced settings belong in config.decision in the managed profile, or decision in an optional project's scape.agent.json:
json
{
"type": "cloudflare",
"accountId": "YOUR_32_CHARACTER_CLOUDFLARE_ACCOUNT_ID",
"model": "clef-flash",
"apiKeyEnv": "CLOUDFLARE_API_TOKEN",
"timeoutMs": 5000,
"maxRequests": 500,
"minIntervalMs": 1000
}1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Replace the account placeholder with the 32-character hexadecimal account ID. This is the decision object, not a complete agent configuration; retain your name, conversation provider and other settings. Omit decision to disable it. behavior.enabled: false and a top-level custom policy cannot be combined with the built-in decision setting. Custom policies can compose the public helpers directly instead.
| Field | Meaning |
|---|---|
type | typesafe, cloudflare, system-one, openai-compatible or custom. |
model | Defaults to jev-latest for TypeSafe and clef-flash for Cloudflare. Cloudflare also accepts clef. Required for other HTTP endpoints; optional for a custom adapter. |
baseUrl | TypeSafe defaults to https://api.typesafe.ai/v1/systemone. Cloudflare defaults to https://api.cloudflare.com/client/v4/accounts. Named endpoints are pinned. For system-one, supply the full POST endpoint; for openai-compatible, supply the base URL before /chat/completions. Optional custom adapter input. |
accountId | Required only for Cloudflare: 32 hexadecimal characters. |
apiKeyEnv | Environment variable name, never the key itself. Defaults: TYPESAFE_API_KEY, CLOUDFLARE_API_TOKEN, or SCAPE_DECISION_API_KEY for compatible endpoints. Custom adapters default to no key. Set null for an endpoint requiring no authentication. Scape agent access variables are prohibited. |
adapter | Required only for custom. Trusted local JavaScript file, relative to the project directory or absolute. Guided setup saves an absolute path. |
timeoutMs | Default 5,000; range 250–30,000 ms per evaluation. Starts after pacing. |
maxRequests | Default 500; range 1–100,000 evaluations per process. Separate from conversation limits.maxModelCalls. |
minIntervalMs | Default 1,000; range 250–60,000 ms between evaluation starts. Waiting remains cancellable. |
Entered keys are stored with the same owner-only permissions as the managed profile, without encryption at rest. Changing decision provider, endpoint, Cloudflare account or adapter file does not reuse the old saved decision key. Choosing an environment variable saves its name instead of its value. Protect the managed profile.
Budgets and fallback
Decisions run on relevant turns, not every observation or animation frame. With a decision model enabled, scheduled greeting and idle activity decisions can incur requests. While alone or in an active quiet/wait pause, the shared runner skips decision inference. Conversation requests occur only when the selected behavior needs them.
The request budget survives empty-world sleep and re-entry. Requests interrupted after dispatch count toward the limit. Restarting the process resets request counts. Request limits do not calculate currency costs; use your providers' spending controls too.
If an evaluation fails, times out or returns invalid answers, the runner reports it and disables decision inference for the rest of that run. Exhausting the decision request budget does the same. Shared rules and the conversation model continue. There is no automatic paid retry. Correct the configuration and restart to re-enable decisions. Missing credentials or an unloadable custom adapter are configuration errors caught before world entry.
Conversation-provider failures and its overall request-budget exhaustion retain their existing stop behavior. A decision timeout does not terminate the agent. Cancellation caused by new activity discards that turn and permits a later decision.
Build a custom adapter
Implement the common contract when your model uses another API or you want your own classifier. The default factory receives only the configured model, endpoint and decision key. It returns evaluate(request, { signal }) and optionally close().
js
// decision-adapter.mjs — example for a custom authenticated JSON service
import { providerJSON } from '@scape/agent-mcp/providers';
export default function createAdapter({ model, baseUrl, apiKey }) {
return {
async evaluate({ state, questions }, { signal }) {
// Adapt the request and response here to your own service's contract.
// This example assumes it already accepts typed questions.
const result = await providerJSON(baseUrl, {
method: 'POST',
signal,
headers: {
'Content-Type': 'application/json',
...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),
},
body: JSON.stringify({ model, state, questions }),
});
return { answers: result.answers };
},
};
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Use an optional installed agent project if your adapter imports @scape/agent-mcp as above. Relative or absolute adapter files still follow normal Node.js module resolution; a managed profile does not install dependencies for them. An adapter using only built-in APIs needs no project dependencies. A configured custom module is trusted local code, not a sandbox; it can access anything your process can access. Do not load code suggested by in-world messages.
Input contains a state value and a map of typed questions. Return one answer per question ID:
| Question | Answer |
|---|---|
choice, with named criteria options | { "type": "choice", "choice": "ONE_OF_THE_OPTIONS" } |
score, with an ordered criteria array | { "type": "score", "score": 1.4 } within 0 through criteria.length - 1 |
noul, a yes/no proposition | { "type": "noul", "noul": 0.8 } within 0 through 1 |
Choice and score answers may include probabilities covering every permitted option or rubric index; their values must be finite, within 0–1 and sum approximately to 1. Optional confidence must be within 0–1. Unknown choices, missing answers and invalid values fail validation. Extra response metadata is discarded. The shared social questions currently use choices; the public client supports all three question types for custom policies.
Do not fabricate probability distributions for a model that returns only a choice. LLM-estimated confidence is not interchangeable with a specialized decision model's probabilities. The structured-output adapter requests the minimal typed values, without confidence or distributions. Behavior selects validated choices; it does not assume those choices are guaranteed correct.
Honor signal to stop your provider request and its costs. The client rejects late results even when an adapter ignores cancellation, but cannot stop work inside arbitrary custom code. Bound your own provider responses and do not log credentials, request bodies or raw provider errors. The common client accepts 1–64 questions, 2–64 options per choice and 2–32 levels per score; input is limited to 128,000 JSON characters, and built-in HTTP responses to 2 MB.
Compose with a custom policy
Import createDecisionClient from @scape/agent-mcp/decision. Create one client per owner process and reuse it across sessions to preserve its budget. Pass it as decision to createWorldBehavior, alongside your conversation policy. Close the client after all sessions finish. Alternatively call client.evaluate() yourself with typed questions; a null result means you must apply your own fallback. Calls must be serialized. Shared behavior expects the validated answers produced by this client.
See runtime composition and the exact decision declarations.
Provider references
The built-in adapters follow TypeSafe's System One API quickstart and Cloudflare's Clef REST API. Cloudflare calls use the account-scoped Workers AI endpoint and unwrap its result envelope. System One-compatible endpoints use the same state/questions contract. The structured-output adapter uses Chat Completions with a strict JSON schema and no tools.
Compatibility tests use simulated provider responses and local MCP/HTTP fixtures. They verify request formats, parsing, limits, cancellation and credential separation, not the decision quality or availability of every hosted or local model.
