stackbone.settings

Typed, read-only access to the workspace settings an operator edits in the dashboard. Your code asks for a key and gets the value in effect right now. There is no write path here: the dashboard owns the values.

Mental model

A workspace carries two sets of knobs, and they belong to two different people.

Surface Who decides the keys Who writes the values
stackbone.config You, in your own config.schema.ts. The dashboard.
stackbone.settings The platform. Values its own built-in features read. The dashboard.

stackbone.settings covers the second kind. It offers no writes by design: a second, unvalidated write path would let an agent overwrite a choice an operator made in the UI.

The values live in your agent's own Postgres, and the SDK reads them over the same handle as stackbone.database, so a read still works when the control plane is unreachable. The runtime injects everything the read needs, so there is nothing for you to configure.

Read one setting

import { stackbone } from '@stackbone/sdk';

const { data: model, error } = await stackbone.settings.get('defaultModel');

if (error) {
  // Nobody picked a value, or the read failed. Fall back to your own default.
  console.warn(`No workspace default model: ${error.code}`);
} else {
  console.log(`Workspace default model: ${model}`);
}

Reads never fill in defaults for you. That keeps "the operator picked nothing" apart from "the operator picked the value that happens to be the default".

Situation What you get
Nobody ever set the key error.code: 'settings_not_found'
Set, then explicitly cleared data: null
Set to a value data: '<the value>'

Read everything at once

import { stackbone } from '@stackbone/sdk';

const { data: settings, error } = await stackbone.settings.getAll();

if (error) {
  console.warn(`Settings unavailable: ${error.code}`);
} else {
  console.log(settings); // { defaultModel: 'openai/gpt-4o', autoMapModel: null }
}

getAll() returns only the keys somebody wrote, so a workspace nobody has configured answers with an empty object. The result is a partial of WorkspaceSettings, a type the SDK re-exports so your code and the dashboard agree on the same key names:

import type { WorkspaceSettings } from '@stackbone/sdk';

The keys today

Key What it controls
defaultModel The workspace's general-purpose chat model, which is what a platform-owned workflow asks for when nothing more specific is set. Picked during the guided first run.
autoMapModel Model the built-in Auto-map workflow asks for, overriding defaultModel for that workflow alone. null means fall back to defaultModel.
guardrailModel Model the model-backed guardrail checks ask for. null falls back to the platform default (openai/gpt-4o-mini).
judgeModel Model that grades the rubric criteria of an eval suite, for every criterion that names no model of its own. null falls back to the platform default (openai/gpt-4o-mini).
simulatorModel Model that plays the end user when an eval case needs a simulated reply. null falls back to the platform default (openai/gpt-4o-mini). Kept apart from judgeModel so grading stays independent.

These settings pick models for platform-owned work only. They do not govern your agents: an agent names its own model in its own code. The built-in RAG ingest workflow also keeps its embedding model pinned, because stored vectors have a fixed width and swapping the model would invalidate them.

The list grows as the platform adds knobs. A workspace written by a newer version may carry keys an older reader has never heard of, and reading never fails because of them.

Errors

Every call returns the usual { data, error } envelope.

Code Means
settings_not_found The key is valid but nobody has written it. Use your fallback.
settings_invalid_request An empty key reached get().
settings_not_configured This agent's database predates the settings table. Run stackbone db migrate up.
settings_unavailable The database read itself failed.
database_not_configured This agent has no database, so there is no settings row to read.

A failed read is rarely a reason to stop. For a knob with a sensible fallback, treat any error as "nothing picked" and carry on. Asking for the model the Auto-map workflow should use looks like this:

import { stackbone } from '@stackbone/sdk';

const { data: settings, error } = await stackbone.settings.getAll();

if (error) {
  throw new Error(`Could not read workspace settings: ${error.message}`);
}

// autoMapModel overrides defaultModel; null on both means nobody has picked one.
const model = settings.autoMapModel ?? settings.defaultModel;

if (!model) {
  throw new Error('No model configured. Pick one on the Workspace settings screen.');
}

What's next

  • stackbone.config reads the configuration you declare for your own agent, with the same envelope and the same fallback pattern.
  • stackbone.ai is the client that calls the model these settings name.
  • Guardrails are the other thing an operator configures in the dashboard and your code never imports.
BUILT WITH ❤️ FROM CANADA AND SPAIN