Identity profiles and runtime
A named identity profile is a config directory — .gsloth/.gsloth-settings/<name>/ — that
carries its own llm block, prompt files, and tool selection. Selecting one with -i <name> swaps
the entire project-file config layer for that directory, so one team, one task, or one model can be
a single-flag switch with nothing to edit between runs. This page is the reference for profiles, for
handing a sub-task to a subagent running under a different profile (subagents), and for the two
runtime knobs that sit alongside them — the AG-UI server config and the agent.backend selector.
For the model-switching recipe (a cheap profile for questions, a strong one for review), see Choose and switch models; this page is the deep reference it points to.
The main use case: a DevOps identity with its own model, guidelines, and review prompt
Section titled “The main use case: a DevOps identity with its own model, guidelines, and review prompt”Goal: your DevOps team reviews PRs against infra/security concerns with their own model and their own review checklist, while developers keep the default project config — no shared config to fight over.
Scaffold a profile, seeding it with the model DevOps wants:
gth config profile create devops --model claude-sonnet-4-5That writes .gsloth/.gsloth-settings/devops/.gsloth.config.json. Drop the DevOps-specific prompt
files next to it in the same directory — an infra/security .gsloth.guidelines.md and a
.gsloth.review.md review checklist:
.gsloth/.gsloth-settings/devops/.gsloth.config.json.gsloth/.gsloth-settings/devops/.gsloth.guidelines.md.gsloth/.gsloth-settings/devops/.gsloth.review.mdNow review a PR under that identity:
gth -i devops pr 42The config, guidelines, and review prompt all come from the devops/ directory instead of the
project defaults. Any prompt file you didn’t create in the profile falls back to the installation
default, so you only author the ones DevOps needs to differ on. Run gth pr 42 without -i and the
config resolves from the default .gsloth/.gsloth-settings/ directory as usual — developers are
unaffected.
Identity profiles
Section titled “Identity profiles”Sometimes two different teams have different perspectives of a project. For example, developers may want to review the code for code quality; DevOps may want to be notified when some configuration files or docker image change. Their configurations of Gaunt Sloth may be so different that it is better to keep them in complete separation. Identity profiles define different Gaunt Sloth identities for different purposes.
Identity profiles can only be activated in directory-based configuration. When
gth -i devops pr PR_NO is invoked, the configuration is pulled from the
.gsloth/.gsloth-settings/devops/ directory, which may contain a full set of config files:
.gsloth.backstory.md.gsloth.config.json.gsloth.guidelines.md.gsloth.review.mdWhen no identity profile is specified in the command, for example gth pr PR_NO, the configuration
is pulled from the .gsloth/.gsloth-settings/ directory.
-i / --identity-profile (or its alias --profile) overrides the entire configuration directory,
which means it should contain a configuration file and prompt files. In the case where some prompt
files are missing, they will be fetched from the installation directory. (The individual
prompt files — backstory, guidelines, system, review, and the per-mode prompts — are
resolved from the selected profile directory first.)
Precedence. A selected profile replaces the project-file layer of the config cascade with the profile directory’s config; everything else stacks as usual:
explicit CLI flags (-c, --model, --verbose, -w) > profile-dir config > global ~/.gsloth config > built-in defaultsSo a profile is the highest-precedence file layer, still overridable by explicit command-line
flags, and still sitting on top of your global ~/.gsloth config and the built-in defaults. Naming a
profile that has no config file of its own is an error: the run stops rather than silently falling
back to some other config — not to your global ~/.gsloth config, and not to the project’s own
plain .gsloth.config.* either, which is the fallback you would otherwise get and the surprising
one. A mistyped -i therefore tells you so, instead of running under a model you did not choose.
Where a profile is looked up. By default, in the project: .gsloth/.gsloth-settings/<name>/,
searched from the working directory up to the repository root. Add
-g/--global and the same name is looked up in
~/.gsloth/.gsloth-settings/<name>/ instead — your own profiles, in a repository that knows nothing
about them. The two are separate namespaces: a profile that exists only in the project is not found
under -g, and vice versa.
Creating a profile
Section titled “Creating a profile”Two ways to create a profile, depending on how you want it seeded:
-
gth init -i <name>walks the same CFG-2 provider/model dialog as a plaingth init, then writes into the named profile instead of the unscoped config. Use this when you want to pick the provider and model interactively (from the live catalog, preferred models starred) rather than seed from something that already exists. Add-gto create the profile under~/.gsloth/.gsloth-settings/<name>/instead of the project:Terminal window gth init -i test2 # .gsloth/.gsloth-settings/test2/.gsloth.config.jsongth init -g -i test2 # ~/.gsloth/.gsloth-settings/test2/.gsloth.config.jsongth init -i <name> <provider>(the scriptable path, e.g.gth init -i test2 anthropic) skips the dialog and writes the project profile directly; add-gto target the global profile instead. -
gth config profile create <name>scaffolds a new profile directory (.gsloth/.gsloth-settings/<name>/.gsloth.config.json), seeded from your current effective config (or a minimal template when none resolves) and schema-validated before it is written. Pass--model <id>to set the profile’s model, and--forceto overwrite an existing profile. Use this when the new profile should start as a copy of what you already have.For example, to add a cheap flash-lite profile alongside your normal setup and then run under it:
Terminal window gth config profile create cheap --model gemini-2.0-flash-litegth --profile cheap ask "summarise the open TODOs in this repo"
Either way you end up with an ordinary config file at .gsloth/.gsloth-settings/<name>/.gsloth.config.json
(or its global counterpart) that you can go on to edit — adjust its tools, prompts, or provider as needed.
Named-profile subagents (subagents)
Section titled “Named-profile subagents (subagents)”subagents lets the agent delegate a sub-task to a subagent that runs under a different
named profile — its own model, tools, and prompt — instead of the parent’s.
The typical use: keep the parent on a strong (expensive) model but hand routine search/recall work to
a cheap one, so the bulk of the tokens are spent on the cheap model.
Each entry names a subagent (the name the model selects it by) and the profile the child resolves:
{ "llm": { "type": "anthropic", "model": "claude-opus-4-1" }, "subagents": [ { "name": "recall", "description": "Cheap read-only search/recall.", "profile": "cheap" } ]}To make the example above run, create the cheap profile it references, then start a coding session —
when the model delegates a recall task, that subagent runs on gemini-2.0-flash-lite, not on the
parent’s claude-opus-4-1:
gth config profile create cheap --model gemini-2.0-flash-litegth codeThe child resolves the named profile through the same config cascade a top-level --profile run does,
so it picks up that profile’s model, tool selection, and prompt files. A subagent whose profile has
no config directory is an error, exactly as selecting a missing profile with --profile is.
Not dispatched yet. No agent backend spawns subagents at present, so a declared
subagentsblock has no effect on a run. It stays a valid config key rather than an error, and a run that declares one prints a warning naming the subagents it did not use — so the setting is announced, never quietly ignored. Write the block now if you want it in place; expect no delegation until subagent dispatch ships.
AG-UI Server Configuration
Section titled “AG-UI Server Configuration”The api ag-ui command reads its settings from commands.api in your config file.
| Field | Type | Default | Description |
|---|---|---|---|
commands.api.port |
number |
3000 |
Port the AG-UI server listens on |
commands.api.cors.allowOrigin |
string |
"http://localhost:3000" |
Access-Control-Allow-Origin header value |
commands.api.cors.allowMethods |
string |
"POST, GET, OPTIONS" |
Access-Control-Allow-Methods header value |
commands.api.cors.allowHeaders |
string |
"Content-Type, Accept" |
Access-Control-Allow-Headers header value |
Example config for the Galvanized Pukeko web client on port 5555:
{ "llm": { "type": "anthropic", "model": "claude-sonnet-4-5" }, "commands": { "api": { "port": 3000, "cors": { "allowOrigin": "http://localhost:5555", "allowMethods": "POST, GET, OPTIONS", "allowHeaders": "Content-Type, Accept" } } }}Note: The port flag
--porton the CLI overridescommands.api.port.
Agent Backend (agent.backend)
Section titled “Agent Backend (agent.backend)”Gaunt Sloth ships one agent backend, lean — a plain LangChain agent carrying Gaunt Sloth’s own
toolset: filesystem, hardened dev/shell, and the gth_checklist planning tool. It is what every
command runs, and what runs when the key is absent, so setting it changes nothing:
{ "llm": { "type": "anthropic", "model": "claude-sonnet-4-5" }, "agent": { "backend": "lean" }}"lean" is the only accepted value. The key is kept so a config can state what it runs on, and so
a second backend has a name to be selected by; a value that is not "lean" is a config error
rather than a silently ignored key.
A config carrying the retired "backend": "deep" fails to load, with a message naming the
replacement — see Migrating to 2.0 for what to change and what it costs you.