Documentationv1.8.1Website ↗GitHub ↗
Browse documentation

Configuration in depth

Main configuration, field by field

Read runtime.config.json from top to bottom. Understand what each section controls, which defaults matter, and which settings belong in another file.

On this page

You do not have to fill in every supported field. Start from the configuration created by onboarding, then change the part that owns your requirement. This page explains the main file; the model-file reference and request-runner reference go inside the files it links to. Model calibration turns that reference into a practical tuning exercise.

Find the files before editing

The usual consumer layout is:

my-abot/
  runtime.config.json          # connections, storage, tools, file references
  models/
    default.config.json       # one model's identity, route and calibration
  request-runner.config.json # step mappings, budgets, timeouts, instruction files
  methodologies/            # additional Markdown guidance
  .env                      # credentials; keep private
  .runtime/                 # saved runtime state; keep private

Paths can differ. LLM_RUNTIME_CONFIG_FILE selects a different main file. A configRef for a model or request runner is relative to the main config file, not to the terminal’s current directory. Ordinary relative storage paths are resolved from the consumer root. Do not move files without checking both kinds of path.

The load order is built-in defaults → configuration file → supported environment variables. An environment variable can explain why changing a JSON value appears to do nothing. JSON must have quoted keys, no comments and no trailing commas. Save a private copy before editing.

Which value wins?

There is no automatic environment-variable equivalent for every nested JSON field. Only explicitly supported variables override the main file. For example, MODEL_GATEWAY_URL is recognized; inventing LLM_RUNTIME_TEMPERATURE will not tune a model.

The default loader reads .env from the consumer root, but does not overwrite a variable already present in the process environment. If a service already exports MODEL_GATEWAY_URL, editing the same name in .env will not win. The dotenv loader also runs once per process; a file edit alone does not refresh an already-running host.

Situation Effective result
JSON sets logging.enabled: false, with no trace override Runtime trace writing is disabled.
JSON sets logging.enabled: false, process has LLM_RUNTIME_TRACE=1 The explicit trace override enables it.
JSON has a gateway address, process has both gateway URL variables MODEL_GATEWAY_URL wins over the alias SIMPLE_LLM_SERVER_URL, then the JSON value.
.env contains a value, but the launching process already has that variable The existing process value is retained.

For library hosts, explicit loadRuntimeConfig options introduce another layer: a supplied configPath selects the main file ahead of LLM_RUNTIME_CONFIG_FILE, and a supplied profileId selects the environment ahead of LLM_RUNTIME_PROFILE. Passing an explicit env object makes that object the loader’s environment source rather than automatically loading .env. These are host API options, not extra fields to add to runtime.config.json.

Read the main file as a map

This is the shape of the published starter, shortened to one environment. It is not a standalone configuration to paste over your working file: the referenced model and request-runner files must exist, and the model must use a real provider/model ID.

{
  "agentBridgeUrl": "ws://127.0.0.1:8787/abot/agent-bridge",
  "modelGatewayUrl": "http://127.0.0.1:3000",
  "environment": {
    "default": "prod",
    "paths": {
      "sharedDir": ".runtime/shared",
      "compiledDir": ".runtime/compiled",
      "workspaceDir": "workspace"
    },
    "profiles": {
      "prod": {
        "paths": {
          "runtimeDir": ".runtime/prod",
          "agentWorkDir": ".runtime/prod/agent-work",
          "sessionsDir": ".runtime/prod/sessions",
          "attachmentsDir": ".runtime/prod/attachments"
        }
      }
    }
  },
  "webUi": { "openOnRuntimeServiceStart": false },
  "logging": {
    "enabled": true,
    "rotation": { "maxFileSizeMb": 20, "maxFiles": 10, "maxAgeDays": 7 }
  },
  "plugins": { "enabled": true, "allow": ["*"], "deny": [] },
  "models": {
    "providers": {
      "provider": {
        "type": "ollama",
        "baseUrl": "http://127.0.0.1:11434",
        "keepAlive": "3m"
      }
    },
    "profiles": { "default": { "configRef": "./models/default.config.json" } }
  },
  "longTermMemory": { "enabled": false, "emitClientEvents": false },
  "requestRunner": { "configRef": "./request-runner.config.json" }
}

Read it in this order: where state lives, which provider and model exist, which tools are available, then optional UI, memory, logging and timing controls. The main file is not a prompt and does not prescribe a fixed agent workflow.

Connections: gateway versus provider versus bridge

Field Meaning When to change it
modelGatewayUrl The runtime’s model-gateway service address. Default: http://127.0.0.1:3000. The gateway runs at a different reachable address. This is not the Ollama URL or the Web UI URL.
agentBridgeUrl WebSocket address used by the default host for optional bridge integration. Default: ws://127.0.0.1:8787/abot/agent-bridge. You deliberately use an external bridge. Ordinary direct Web UI use does not require setting up a bridge server.
agentBridgeToken An optional bridge authentication token. Prefer supplying its value through AGENT_BRIDGE_TOKEN, not JSON. Never publish it.

MODEL_GATEWAY_URL (or its supported alias SIMPLE_LLM_SERVER_URL) overrides the gateway address. AGENT_BRIDGE_URL overrides the bridge address. Provider addresses are configured separately under models.providers.

Example: ABot in a container and Ollama on the host are not the same machine for 127.0.0.1. Set the provider’s reachable address; do not replace modelGatewayUrl with Ollama’s port to work around a connection failure.

Environments and storage paths

environment.default selects a named entry in environment.profiles. An explicit LLM_RUNTIME_PROFILE overrides that selection. prod and dev are names, not automatic safety modes: permissions still need to be configured.

An environment profile changes paths, not every other part of the config. Do not put a second models, plugins or logging object inside environment.profiles.dev and expect it to overlay the root configuration. A different model is selected through the model catalog and request policy, not by inventing an environment-local catalog.

environment.paths holds shared/base path choices. environment.profiles.<id>.paths supplies paths for that environment. The following keys are available in both:

Path key What it stores or selects What changing it means
runtimeDir Live state root for the environment: hosting, scheduling, memory and plugin state, plus default subdirectories. You are selecting a different state location, not moving existing data.
agentWorkDir Primary working root for plugin-created or modified files. Relative plugin paths and . resolve here unless a project supplies its working context. A different artifact location. It is not a shell sandbox.
sessionsDir File-backed conversation store. Pointing somewhere empty makes old conversations unavailable there; it does not delete or migrate the old directory.
attachmentsDir Runtime-managed uploaded files referenced by conversations and requests. Preserve the relationship between session metadata and its attachments.
traceFile Active runtime observability JSONL file. Changes where that trace is written/read, not all application logs.
workspaceDir Optional workspace context source directory. Context source, not another model or permission setting.
sharedDir Generated state shared across environments, such as service logs. Keep it distinct from private environment state when isolation is intended.
compiledDir Optional generated context artifacts, such as file-provider skill manifests. Not the source repository, installed package or user output folder.

Without explicit environment paths, the base defaults include .runtime, agent-work, workspace, .runtime/shared and .runtime/compiled. Sessions, attachments and traces normally derive from the resolved runtime directory. The starter explicitly uses .runtime/prod and .runtime/dev; do not confuse its choices with universal defaults.

A named profile without an explicit runtime directory derives an isolated directory from the base and a hash of the profile ID. Existing populated state is never silently reassigned: runtime_environment_storage_assignment_required means you must explicitly identify which environment owns it. Use the upstream environment migration example, not a guessed directory.

Supported overrides include LLM_RUNTIME_DIR, LLM_RUNTIME_AGENT_WORK_DIR, LLM_RUNTIME_SESSIONS_DIR, LLM_RUNTIME_ATTACHMENTS_DIR, LLM_RUNTIME_TRACE_FILE, LLM_RUNTIME_WORKSPACE_DIR, LLM_RUNTIME_SHARED_DIR and LLM_RUNTIME_COMPILED_DIR. These take precedence over JSON. In particular, LLM_RUNTIME_DIR becomes a shared base when a profile is selected; it can defeat an intended explicit directory assignment if left set.

The root-level paths object is also supported. Its values provide the base, with corresponding environment.paths values taking precedence. Prefer the environment layout for new setups instead of maintaining competing copies.

A concrete two-environment example

The following is a replacement shape for the environment section only, illustrating explicit directories. Do not apply it to an existing installation without preserving the directories that already own your data.

{
  "environment": {
    "default": "prod",
    "paths": {
      "sharedDir": ".runtime/shared",
      "compiledDir": ".runtime/compiled",
      "workspaceDir": "workspace"
    },
    "profiles": {
      "prod": {
        "paths": {
          "runtimeDir": ".runtime/prod",
          "agentWorkDir": ".runtime/prod/agent-work"
        }
      },
      "dev": {
        "paths": {
          "runtimeDir": ".runtime/dev",
          "agentWorkDir": ".runtime/dev/agent-work"
        }
      }
    }
  }
}

With no environment overrides and consumer root /work/my-abot, selecting dev uses /work/my-abot/.runtime/dev. Omitted sessionsDir, attachmentsDir and traceFile derive from that selected directory: sessions, attachments and logs/runtime-debug.jsonl. Shared and compiled directories remain shared because the example puts them in the base path section. The workspace source remains shared too.

This is an important exception to a simplistic “profile inherits every path” rule. With a named environment selected, sessions, attachments and the trace derive from that environment’s runtime directory unless explicitly set on the profile or overridden by environment variables. They do not inherit a base state-file path that would silently mix environments. Other paths such as agentWorkDir, sharedDir and compiledDir can inherit their base values.

The example deliberately gives agentWorkDir a separate value in each profile. Isolating state does not automatically isolate every tool’s output folder. Explicit project working folders and tools with their own access rules remain separate concerns; dev is not a sandbox.

Changing environment.default does not copy production conversations into development. Renaming a profile that uses a derived hashed namespace can select a new state directory. Before changing names or storage, record the resolved paths, preserve their contents, and check which environment the UI is displaying. Do not diagnose “all chats disappeared” as data deletion until checking the selected namespace.

Providers and model profiles

models.providers names connections; models.profiles names usable model configurations. A provider ID is an identifier you choose, and the model profile’s provider must match it exactly.

Provider field Meaning
type Registered adapter, such as ollama or openai. Naming an unknown type does not install an adapter or select a fallback.
baseUrl Provider endpoint. The OpenAI adapter defaults to https://api.openai.com/v1; Ollama must be reachable from ABot.
apiKeyEnv Name of the environment variable containing the API key, such as OPENAI_API_KEY. It is never the actual key.
keepAlive Ollama model residency setting passed as keep_alive, for example 3m. It is not a request timeout.
settings JSON-safe settings interpreted by that provider adapter. Arbitrary keys do not become universal ABot settings.

Provider adapters have their own fallback rules. Do not apply the root-file environment precedence rule to every provider field:

Connection setting Effective order in the built-in adapter
OpenAI endpoint Explicit provider baseUrl → OPENAI_BASE_URL → https://api.openai.com/v1.
OpenAI credential Read the environment variable named by apiKeyEnv; if omitted, use OPENAI_API_KEY. The value is read by the gateway process.
Ollama endpoint Explicit provider baseUrl → the gateway’s configured Ollama fallback (normally OLLAMA_URL or http://127.0.0.1:11434).
Ollama residency Explicit keepAlive → 3m. This asks the provider how long to keep a model resident; it does not promise that memory is always available.

For example, setting OPENAI_BASE_URL does not override an explicit models.providers.openai.baseUrl. If the gateway is a separate process, its credentials must be available to that process, not just the browser or the Runtime process.

Provider type must be a valid adapter identifier, apiKeyEnv a valid environment-variable name, and optional string fields non-empty strings. The main-file validator is not an endpoint health check. The setup wizard imposes additional URL rules for its connection form; valid raw JSON does not imply that a remote service is reachable or compatible.

For example, merge a named connection into the existing models.providers object:

{
  "openai": {
    "type": "openai",
    "apiKeyEnv": "OPENAI_API_KEY"
  }
}

An entry such as "default": { "configRef": "./models/default.config.json" } loads the separate model file. You can define a model inline, but separate files make per-model calibration easier to maintain. The model file owns its label, provider, model, contextWindowTokens, execution, generation, capabilities, context, provider options, supportsThinking, plugins.deny and calibration. Follow the calibration walkthrough rather than putting every setting into the main file.

Two less common catalog sections are:

  • models.embeddingProfiles: named embedding models with provider, model, optional label and provider options. They do not accept generation/reasoning/context-window settings. Memory points to one of these IDs.
  • models.invocationProfiles: named invocation overrides referencing a base profileId, with optional generation, context and format. Keep them only when you need a deliberate invocation target; ordinary per-model tuning belongs in calibration.

models.defaults is also accepted by the model catalog. Its context provides projection defaults and overrideClientPreference controls whether configured selection ignores the client’s model choice. The catalog can also describe profileId, roles and steps, but ordinary Runtime requests take their profile and step mappings from the linked request runner: the request policy replaces the catalog’s profileId and steps, and does not copy its roles. Use the runner for ordinary request selection; changing a similarly named root-catalog field may not affect the run you are testing.

One connection, more than one profile

A provider connection is reusable. You do not need to duplicate an API key or endpoint to create two model profiles with different routes or calibration. Merge this fragment into the existing catalog; replace the two filenames with files that actually exist:

{
  "models": {
    "providers": {
      "ollama-local": {
        "type": "ollama",
        "baseUrl": "http://127.0.0.1:11434",
        "keepAlive": "3m"
      }
    },
    "profiles": {
      "local-assistant": { "configRef": "./models/local-assistant.json" },
      "local-reviewer": { "configRef": "./models/local-reviewer.json" }
    }
  }
}

Both model files can use "provider": "ollama-local" while choosing their own actual model ID and settings. Adding the second profile does not automatically send review steps to it; that requires deliberate selection or a supported runner/calibration mapping. It also does not create a second model server.

Use the model reference for file overlays, generation and calibration. Keep provider connection settings here and model behavior in the profile. The runtime validates bindings; declaring a provider does not test network access, validate billing or download weights.

Plugins: availability, not approval

Field Meaning and default
plugins.enabled Whether installed plugins may load. Default true.
plugins.allow Selection from the installed catalog. ["*"], omission, and an empty list all select the catalog; an empty list does not mean “no tools.”
plugins.deny Removes matching capabilities after the allow-list. Default empty; deny wins.
plugins.disabledPluginIds Exact plugin IDs disabled independently of tool selectors. These are literal IDs, not wildcard expressions. Default empty.

Allow/deny selectors can name *, a plugin, a capability or plugin.capability. For example, this partial root section leaves the catalog enabled but denies one file-reading tool:

{
  "plugins": {
    "enabled": true,
    "allow": ["*"],
    "deny": ["filesystem.read_file"]
  }
}

It does not prevent another enabled tool, such as a permitted shell command, from reading a file. It is a tool-selection rule, not filesystem isolation. A model’s plugins.deny can further restrict availability, never expand it. Ask/Full/FULL+ approval modes are separate and are not a root permissionMode field to add here.

Plugin-specific settings and secrets live outside the package in .runtime/plugin-configuration.json. Use Plugins → Configure; do not invent provider keys under the root plugins object. See the plugin guide.

Read the rules as a filter

Suppose your installed catalog contains the filesystem plugin and a separate web tool. With allow: ["filesystem"], only matching filesystem capabilities pass the global allow filter. Adding deny: ["filesystem.read_file"] removes that capability again. Adding the plugin’s exact ID to disabledPluginIds disables its capabilities independently of those selectors.

To disable installed plugins globally, use "enabled": false—not "allow": []. To restore one later, check all relevant restrictions: global enablement, disabled IDs, allow-list, global deny and the selected model’s deny-list. Removing one blocker does not erase the others.

These lists refer to installed IDs and capability names, not display labels or Marketplace URLs. Copy the exact identifier shown by your installation. They do not install a missing plugin, supply its credentials, grant OS permissions or approve an action. Inspect the Plugins workspace after applying a change, then try a small task in Ask mode to distinguish availability from authorization.

The wildcard is the literal selector "*". Matching is otherwise exact: "filesystem.*" is not a supported prefix glob. Use the plugin ID "filesystem" for all of its capabilities, or a specific qualified capability such as "filesystem.read_file" for one. A bare capability name can match that name under different plugins; use a qualified selector when you intend to restrict one owner.

Optional long-term memory

Field Meaning
longTermMemory.enabled Enables passive cross-conversation memory. Default false. Use Memory setup to configure and probe a real embedding model first.
longTermMemory.embeddingProfileId ID under models.embeddingProfiles used for indexing and retrieval. Required for enabled memory.
longTermMemory.emitClientEvents Emits bounded lifecycle status/counts to clients. Default false; it does not expose memory contents or vectors.
longTermMemory.maxRecallCallsPerRequest Maximum core recall_memory calls offered per request. Positive integer, default 5. Not a record-storage limit or a control for the separate explicit-memory plugin.

For example, after creating a working embedding profile named memory-embedding, merge:

{
  "longTermMemory": {
    "enabled": true,
    "embeddingProfileId": "memory-embedding",
    "emitClientEvents": false,
    "maxRecallCallsPerRequest": 5
  }
}

Memory setup is preferable to flipping the boolean: it probes the provider before saving the enabled configuration. A hosted embedding provider receives the text sent for embedding. This section does not enable SPARK collection or replace the separate explicit-memory plugin.

The binding must exist in models.embeddingProfiles, not merely models.profiles. Its provider must also resolve. A conversational model profile with the same name does not satisfy that requirement. When memory is enabled, a missing embeddingProfileId or an unknown embedding-profile ID is a configuration error, not an instruction for ABot to choose one automatically.

maxRecallCallsPerRequest must be a positive safe integer; zero is not the way to disable memory. A value of 2 gives core explicit recall a smaller call allowance than the default 5; it does not mean two stored memories, two results or two lifetime calls. Setting enabled: false stops the optional core-memory feature; it is not a request to delete saved records. Use the Memory workspace when you intend to manage stored information.

Web UI and log retention

Field Default Meaning
webUi.pageSize 20 Positive number of sessions/messages loaded per history page, including SPARK. More history loads on scroll. This is not model context length or a transcript-retention limit.
webUi.openOnRuntimeServiceStart false Whether to open the local Web UI when the Runtime service starts. It does not expose the UI publicly.
logging.enabled true Whether runtime observability writes the active trace file. LLM_RUNTIME_TRACE can override it.
logging.rotation.maxFileSizeMb 20 Size at which the active trace rotates.
logging.rotation.maxFiles 10 Maximum retained rotated siblings, in addition to the active file.
logging.rotation.maxAgeDays 7 Age limit for rotated trace siblings, enforced during writes.

Changing log retention does not delete conversations, SPARK observations, saved memories or every service log. Logs may contain sensitive content; review them before sharing. Increasing pageSize changes UI loading volume, not how much context a model can accept.

pageSize must be a positive integer, not a string such as "30". The startup option must be the boolean true or false, not "false". The rotation fields accept positive numeric values; use whole numbers so the loader’s integer normalization does not introduce surprises. Zero is not a supported “unlimited” or “retain nothing” value.

For example, this main-file fragment changes history loading and chooses a smaller trace-retention budget without disabling tracing:

{
  "webUi": {
    "pageSize": 30,
    "openOnRuntimeServiceStart": false
  },
  "logging": {
    "enabled": true,
    "rotation": {
      "maxFileSizeMb": 10,
      "maxFiles": 4,
      "maxAgeDays": 3
    }
  }
}

This is an illustrative retention choice, not a recommended policy for every installation. Up to four rotated siblings are retained beside the active file, and old rotated files are eligible for cleanup during writes. It is not a precise disk quota or a background deletion timer. If tracing appears disabled despite the JSON, inspect LLM_RUNTIME_TRACE: 0, false and off disable it; other non-empty values enable it. Omit that variable when you want the JSON field to be authoritative.

The Web UI address is a host setting

webUi.host and webUi.port are not supported main-file keys. The launching Web UI host reads LLM_RUNTIME_WEB_HOST (default 127.0.0.1) and LLM_RUNTIME_WEB_PORT (default 5177). A port must be an integer from 1 through 65535; an invalid value falls back to 5177. Always check the startup address rather than assuming a malformed override was accepted.

Changing the listener requires restarting the launching Web UI process, not merely applying model settings. Keep the local bind default unless you have deliberately designed authentication and network access for a different deployment. Changing a host address does not add those protections. openOnRuntimeServiceStart controls the service-start browser-opening hook; it does not configure the listener or promise that every launch path opens a browser.

Timeouts and the request-runner file

The optional root timeouts object accepts positive millisecond values, but an accepted field is not necessarily connected to the ordinary request path. In the published 1.8.1 default host:

Field Meaning and effective control
requestTimeoutMs Loaded as host metadata. The ordinary request lifecycle reads LLM_RUNTIME_REQUEST_TIMEOUT_MS; do not rely on this JSON field alone to change its deadline.
requestInactivityTimeoutMs Loaded as host metadata. The ordinary lifecycle reads LLM_RUNTIME_REQUEST_INACTIVITY_TIMEOUT_MS; the JSON field alone is not its effective control.
modelStepTimeoutMs Accepted compatibility field, not the ordinary runner’s per-step control. Use the runner’s stepDefaults.timeoutMs or the relevant step override.
streamInactivityTimeoutMs Wired into the default model client to limit inactivity while streaming model output.

The loader recognizes matching environment overrides prefixed by LLM_RUNTIME_. LLM_RUNTIME_STREAM_INACTIVITY_TIMEOUT_MS overrides the stream field. Request timers, stream inactivity and runner step timeouts have different owners; use the actual reported failure to identify the one that fired. Do not set every timeout to a large number. A longer deadline does not improve reasoning or enlarge context.

The required requestRunner.configRef points to the separate policy file. Its important fields are:

Request-runner field Meaning
schemaVersion Fresh files use 2. Legacy unversioned files remain supported; do not label them version 1 explicitly.
models.defaults.profileId Base profile for ordinary model calls when applicable.
models.defaults.steps Sparse mapping from internal step ID to model/profile/calibration target. Missing mappings use the same step ID. Preserve deliberate non-identity mappings.
context.outputReserveTokens Leaves input room for output. It is not a generation max_tokens setting.
context.safetyReserveTokens Additional input-budget headroom.
context.attachmentReserveTokens Input-budget headroom for attachments.
stepDefaults.timeoutMs Default timeout for model steps, in milliseconds.
steps.<step>.timeoutMs An explicit timeout for one step.
steps.<step>.instructionRefs Additional Markdown guidance for that step. Paths are relative to the request-runner file.

Use Configuration files for a worked instructionRefs example, and Model calibration to tune one model without changing every profile.

The request-runner reference explains each field in depth, including a worked step-mapping example and the difference between a context reserve and a provider output limit. Do not put the runner’s context or steps directly inside the main requestRunner object: that object accepts only configRef.

A model’s matching calibration.<slot>.timeoutMs can override the runner’s fallback for that invocation. Check it as well when a step still times out after changing the runner.

Legacy flags and settings that do not belong here

featureFlags is a host-consumed map of boolean, number or string values. features is its legacy alias; when featureFlags is present it takes precedence rather than merging the two. Adding an arbitrary flag does not implement a feature. Leave these absent unless a specific integration documents a supported key.

There is no top-level spark, studio, instructions, temperature or permissionMode in the published main-file contract. Configure SPARK and Studio through their workspaces. Model generation belongs to a model profile; additional step guidance belongs in calibration or the request runner. Unsupported fields are rejected by the runtime loader.

Make one change and verify it

Try a non-destructive example: add "pageSize": 30 to the existing webUi object, keeping its other fields. In the configuration workspace, the three similarly named actions have different jobs:

Action What changes What has not happened yet
Apply draft in Raw JSON Parses the JSON draft into the editor’s configuration state. No file save and no Runtime activation.
Save file Saves the selected file through the configuration service. A raw-draft save first applies that draft. Saved settings are not proof that running environments are using them.
Apply & restart Restarts idle Runtime environments using saved settings. It does not save other unsaved editor drafts for you.
  1. Open the configuration workspace and check Config files for the actual linked paths.
  2. In Raw JSON → Config file, select the main runtime file, not a model or runner file.
  3. Edit the existing webUi object. Keep unrelated fields intact and use a number, not a quoted string.
  4. Select Apply draft if you want to review the parsed draft in the editor; then Save file. Alternatively, Save file can apply and save that raw draft directly.
  5. Read the save result. A validation error is not a successful save. A “saved; refresh required” result means the file was saved but the UI could not refresh its canonical view; refresh and inspect it before trying to save an old draft again.
  6. Check that other work is idle, then use Apply & restart. It applies saved settings across environments of this installation, not only the currently visible model.
  7. Reload a history view and load older messages. The page size has changed; your stored history should still be present.

When editing files outside the UI, preserve a private backup and use the activation flow or deliberately restart your own local Runtime after completing active work. Browser refresh alone is not a general configuration reload. A save conflict from another editor/window should be resolved by reloading and reconciling changes, not by blindly overwriting the newer file.

Activation has limits. Apply & restart replaces idle Runtime owners; it is not a restart of the whole Web UI operating-system process. Busy or externally owned work can return “restart required” instead of being forcibly stopped. Changes to the parent process environment or the Web UI listener need a deliberate restart of that launching process.

If replacement startup fails after shutdown, the activation code attempts to restore the previously applied runtime/gateway configuration. That does not roll back your saved JSON files. Correct or restore the saved edit before the next attempt, and inspect the returned status rather than assuming either that the new configuration is active or that the old files were restored.

If the change fails validation, keep the error, restore that edit and check its file/field owner. Do not reset the whole installation. If it saves but appears ineffective, check environment overrides and whether the saved configuration was actually applied.

For model or tool changes, run a small representative task and inspect the result after applying. For storage changes, inspect the resolved paths and existing state before making a move. Treat the published schema and loader as the contract; an editor accepting syntactically valid JSON does not prove the configuration is meaningful.

Diagnose the layer, not just the last error

Symptom First checks
JSON parses, but configuration is rejected Required models and requestRunner.configRef, supported field names, types and referenced files. A fragment from this guide is not a complete installation.
A valid edit has no visible effect Wrong file selected, unsaved draft, saved-but-not-applied configuration, or a supported environment override.
Model calls use a different profile The UI’s selected profile, runner mappings and overrideClientPreference; inspect model.invocation.resolved instead of asking the model.
Tools still do not appear Installed catalog, all global/model restrictions, platform compatibility and plugin configuration. Permission mode cannot restore an unavailable tool.
History looks empty after a path edit Active environment and resolved sessions/runtime directories. Changing a path does not migrate the old state.
A long model call still times out Which timer fired: request deadline, request inactivity, runner step, per-slot override or stream inactivity.

Do not dump the full environment or .env to diagnose precedence: it can contain credentials. Check the specific non-secret setting and relevant status message. Restore only the change under test when comparing behavior.

Search documentation

Search titles, explanations and examples. Everything stays in this browser.