Workspace Config Overlays
How workspace config.toml and mcp.json layer over global AGH configuration without making project copies brittle.
- Audience
- Operators running durable agent work
- Focus
- Workspaces guidance shaped for scanability, day-two clarity, and operator context.
Workspace config lets one project change runtime behavior without changing every AGH session on the machine. The loader starts from built-in defaults, applies global config, then applies the resolved workspace root overlay.
This keeps project behavior portable. Copy a repository with .agh/config.toml, .agh/agents/,
.agh/skills/, and .agh/memory/, register the copied path, and the project-level runtime context
comes with it.
Load Order
The effective config for a resolved workspace is built in this order:
| Order | Source | Notes |
|---|---|---|
| 1 | Built-in defaults | DefaultWithHome(homePaths). |
| 2 | ~/.agh/config.toml | Global operator settings. $AGH_HOME/config.toml when AGH_HOME is set. |
| 3 | ~/.agh/mcp.json | Global top-level MCP sidecar. |
| 4 | <workspace>/.agh/config.toml | Workspace root overlay only. |
| 5 | <workspace>/.agh/mcp.json | Workspace top-level MCP sidecar. |
| 6 | Path normalization and validation | Expands ~ in daemon.socket and memory.global_dir, then validates the final config. |
Workspace additional roots do not contribute config. They can contribute agents and skills, but
only the primary root contributes config.toml and top-level mcp.json.
Create A Workspace Overlay
Create the config file under the project root:
mkdir -p /Users/you/src/checkout-api/.agh# /Users/you/src/checkout-api/.agh/config.toml
[defaults]
agent = "reviewer"
provider = "claude"
[permissions]
mode = "approve-reads"
[limits]
max_sessions = 4
[skills]
disabled_skills = ["public-cloud-deploy"]
[[mcp_servers]]
name = "repo-fs"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/src/checkout-api"]Then register the workspace:
agh workspace add /Users/you/src/checkout-api --name checkout-apiSessions that target checkout-api now inherit the overlay:
agh session new --workspace checkout-apiThe command uses reviewer as the default agent unless you pass --agent.
Merge Rules
TOML overlays are field-aware. A field changes only when the overlay provides that field.
| Shape | Merge behavior |
|---|---|
| Scalar values | Replace the previous value when present. |
| Nested tables | Merge recursively. Omitted nested fields keep previous values. |
Slices such as skills.disabled_skills | Replace the previous slice when present. |
providers.<name> | Merge by provider key. Existing provider fields are kept unless replaced. |
hooks.declarations | Merge by hook name; same-name declarations replace earlier ones. |
[[mcp_servers]] | Merge by MCP server name; same-name servers are patched field by field. |
| Unknown TOML keys | Fail config loading with an unknown-key error. |
| Missing config files | Treated as absent. |
This example keeps the global marketplace URL while changing only skill enablement:
# ~/.agh/config.toml
[skills.marketplace]
registry = "clawhub"
base_url = "https://registry.example.test/api/v1"# <workspace>/.agh/config.toml
[skills]
enabled = falseThe final config has skills.enabled = false, but keeps the global marketplace registry and
base_url.
MCP Sidecars
Top-level mcp.json files are optional. They may use either mcpServers or mcp_servers.
{
"mcpServers": {
"repo-db": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "postgres://localhost/checkout"
}
}
}
}When both key styles appear in the same mcp.json, mcp_servers replaces same-name entries from
mcpServers. When a TOML MCP server and an mcp.json server have the same name, the JSON sidecar
replaces the whole server object at that scope.
Across the session start path, MCP servers are then resolved in this order:
- top-level config MCP servers
- provider MCP servers
- agent MCP servers
- active skill MCP servers
Workspace Agents And Skills
Config overlays do not define agents or skills directly. They change the runtime defaults around the agents and skills discovered by the resolver.
| Goal | Put this in config | Put this in the workspace filesystem |
|---|---|---|
| Change the default agent for one project | [defaults].agent = "reviewer" or agh workspace edit --default-agent reviewer | .agh/agents/reviewer/AGENT.md |
| Disable a noisy skill in one project | [skills].disabled_skills = ["skill-name"] | Keep the skill where it is. |
| Add project MCP servers | [[mcp_servers]] or .agh/mcp.json | Agent/skill-local mcp.json when the server belongs to one agent or skill. |
| Change provider command/model for one project | [providers.<name>] | No filesystem resource needed. |
| Add a project-only skill | No config entry required. | .agh/skills/<name>/SKILL.md |
Workspace registration has one extra override: default_agent. When it is set on the workspace row,
the resolver applies it after loading config by setting defaults.agent for the resolved snapshot.
agh workspace edit checkout-api --default-agent reviewerSet it to an empty value to clear it:
agh workspace edit checkout-api --default-agent ""Concrete Overlay Walkthrough
Global config:
# ~/.agh/config.toml
[defaults]
agent = "general"
provider = "codex"
[permissions]
mode = "approve-all"
[limits]
max_sessions = 10
[skills]
disabled_skills = ["legacy-notes"]Workspace config:
# <workspace>/.agh/config.toml
[defaults]
agent = "reviewer"
[permissions]
mode = "approve-reads"
[skills]
disabled_skills = ["deploy-production", "legacy-notes"]Effective result for the workspace:
| Setting | Final value | Why |
|---|---|---|
defaults.agent | reviewer | Workspace scalar replaces global scalar. |
defaults.provider | codex | Workspace omitted it, so global remains. |
permissions.mode | approve-reads | Workspace scalar replaces global scalar. |
limits.max_sessions | 10 | Workspace omitted the table, so global remains. |
skills.disabled_skills | ["deploy-production", "legacy-notes"] | Workspace slice replaces the global slice. |
.env And AGH_HOME
If a workspace root contains .env, AGH loads it before resolving the AGH home layout for that
config load. That means a workspace can set AGH_HOME for sessions that resolve that workspace:
AGH_HOME=/Users/you/.agh-checkoutUse this carefully. It changes the global config, agents, skills, memory, sessions, logs, socket,
and database locations for that resolved workspace config load. Most projects should prefer
<workspace>/.agh/config.toml for project-specific behavior and keep AGH_HOME stable.
Failure Behavior
| Case | Behavior |
|---|---|
Missing config.toml | Ignored. Defaults and other layers still load. |
Missing mcp.json | Ignored. |
| Unknown TOML key | Loading fails and reports the key path. |
| Invalid TOML duration or type | Loading fails during decode or validation. |
| Invalid MCP JSON | Loading fails with path context. |
| Invalid final config | Loading fails before the workspace snapshot is returned. |
Related Pages
- Workspace Resolver explains when config loading happens.
- Multi-Root Workspaces explains why additional roots do not add config overlays.
- Agent Definitions documents agent-local MCP sidecars.
- Skills Overview documents skill-local MCP sidecars and disabled skill behavior.