Configuration repository
The format of the repository that central configuration reads. For the steps, see Set up central configuration.
Layout
The repository has one control file at its root, and the artifacts it points to. Artifact paths can be anywhere in the repository. This layout is a convention:
assignment.jsonc
artifacts/
mcp/ connector artifacts (.json)
provider/ model provider artifacts (.json)
agents/ agent files (.md)
context/ context files (.md)
skills/ one folder per skill, each with a SKILL.md
vocabulary/ dictation vocabularies (.md)
assignment.jsonc
JSON that also allows comments (
// and /* */) and trailing commas.
| Key | Contains |
|---|---|
schema_version |
The format version. The example repository uses 2. |
artifacts |
One object per kind. Each maps an artifact ID to { "path": "…" }, a path relative to the repository root. |
assignments.projects |
One object per project ID. Each lists the artifact IDs the project gets, by kind. |
The kinds are
mcp, provider, agents, context, skills, and vocabulary. A project can also have:
| Key | Contains |
|---|---|
deny |
Artifact IDs to leave out, by kind. |
mcp_default_on |
Connector IDs meant to start switched on. Not used yet: assigned connectors always start off. |
{
"schema_version": 2,
"artifacts": {
"mcp": { "mcp.docs.v1": { "path": "artifacts/mcp/docs.json" } },
"agents": { "agent.writer.v1": { "path": "artifacts/agents/writer.md" } },
"context": { "context.style.v1": { "path": "artifacts/context/style.md" } },
"skills": { "skill.slides.v1": { "path": "artifacts/skills/slides/" } },
"provider": { "provider.onprem.v1": { "path": "artifacts/provider/onprem.json" } },
"vocabulary": { "vocab.org.v1": { "path": "artifacts/vocabulary/org.md" } }
},
"assignments": {
"projects": {
"proj_sales": {
"mcp": ["mcp.docs.v1"],
"agents": ["agent.writer.v1"],
"context": ["context.style.v1"],
"vocabulary": ["vocab.org.v1"]
}
}
}
}
If the workspace's project isn't listed, or a listed ID isn't registered, nothing is written at that start. What was written at an earlier start stays in place, and the log names the problem.
An artifact ID stands for one version of an artifact. To change one, add it under a new ID. Vocabulary files are the exception: you can edit them in place.
Connector artifacts
An opencode configuration fragment with an
mcp block, and an sds block for Knowledge Worker Agent.
{
"mcp": {
"docs": {
"type": "remote",
"url": "https://mcp.example.com/mcp"
}
},
"sds": {
"description": "Search the team's product documentation.",
"auth": {
"type": "api-key",
"label": "Docs",
"help": "Paste the personal API key from your Docs profile.",
"helpUrl": "https://docs.example.com/api-keys"
}
}
}
The
mcp block uses opencode's format. A remote server has a url, and a local server has a command. Don't include enabled. It's removed, with a warning in the log.
sds.auth fields:
| Field | Description |
|---|---|
type |
How users connect. See the table below. |
label |
Name shown to users. |
help |
Instructions shown to users, for example where to get a key. |
helpUrl |
A link to more help. Only https:// links are shown. |
header |
For api-key: the header that carries the key. Default Authorization. |
scheme |
For api-key: the text before the key. Default Bearer. "" sends the key alone. |
type |
Users see |
|---|---|
oauth |
Sign in, to sign in in the browser. |
none |
Nothing to do. The connector works once it's on. |
setup |
Needs setup, with your help and helpUrl. |
local |
A local command. Nothing to sign in to. |
api-key |
Key needed, and Add key to add their own key. |
sds.description says in one sentence what the connector gives users. Knowledge Worker Agent shows it when it tells users about a connector they haven't set up.
Without an
sds block, users may have no way to connect the server.
Never put a secret in the repository. If a header must carry a shared secret, use opencode's substitution:
{file:/path/to/secret} reads a file, and {env:NAME} reads an environment variable.
Important: A file named in
{file:…} must exist in every workspace the artifact is assigned to. If it's missing, opencode rejects its whole configuration, and no chat works. An unset variable in {env:…} doesn't have this effect, so prefer {env:…}.
Model provider artifacts
An opencode configuration fragment with a
provider block, and an sds block.
{
"provider": {
"onprem": {
"npm": "@ai-sdk/openai-compatible",
"name": "On-premises models",
"options": {
"baseURL": "https://models.example.com/v1",
"apiKey": "{env:ONPREM_API_KEY}"
},
"models": {
"large": {
"name": "Large",
"cost": { "input": 2, "output": 6 },
"limit": { "context": 128000, "output": 8192 },
"tool_call": true
}
}
}
},
"sds": {
"description": "Our own models, hosted on premises.",
"auth": {
"type": "managed",
"secretRef": "ONPREM_API_KEY",
"label": "On-premises models",
"help": "Provided by your administrator."
},
"presets": {
"default": "onprem/large",
"thinking": "onprem/large",
"small": "onprem/large"
}
}
}
The
provider block uses opencode's format. This example is a private endpoint, so it defines everything. Give each model a cost and a limit, or usage shows no cost and no context limit.
For a provider opencode already knows, give only the provider ID,
name, and any whitelist or blacklist. Don't add npm, options, or models, because they replace opencode's own definition.
Key in the provider block |
Description |
|---|---|
whitelist |
Bare model IDs to show. Other models are hidden. Deprecated models can't be listed. |
blacklist |
Bare model IDs to hide. |
sds.auth fields:
| Field | Description |
|---|---|
type |
managed: you provide the key. user-key: each user adds their own key under Accounts. Default user-key. Not used for GitHub Copilot and Google Vertex AI, which keep their own sign-in. |
secretRef |
For managed: the file or environment variable that holds the key. Only its presence is checked. |
label |
Name shown under Accounts. |
help |
Text shown under Accounts. |
sds.description says in one sentence what the provider gives users, as for connectors.
sds.presets fields:
| Field | Model used for |
|---|---|
default |
Default. |
thinking |
Thinking. |
small |
Short background jobs, such as naming chats and writing day notes. |
Each value is
provider/model. When several providers name a preset, the first one assigned wins.
Assigned providers are shown only when
KWA_CENTRAL_CONFIG is on.
Agent, context, and skill artifacts
| Kind | Format | Where it's used |
|---|---|---|
agents |
An opencode agent file (.md). |
Listed under Provided by IT when users choose an agent. |
context |
A single Markdown file (.md). A path to a folder stops the whole run. |
Added to the instructions of every chat. |
skills |
A folder with a SKILL.md file and any scripts it uses. The path points to the folder. |
Listed in the Toolbox. |
Files are copied as they are, without their execute permission. Anything in a skill's folder reaches every user of the project. Artifacts must not contain fixed paths to where they're written. For more information, see Write skills and agents for your teams.
Vocabulary artifacts
A Markdown file with one or more tables. Every table row with a Term is read. Other text is ignored.
| Term | Heard as | Notes |
| --- | --- | --- |
| Acme Cloud | "acne cloud" | the product |
| PLATFORM | | a project key |
| Column | Description |
|---|---|
| Term | The written form. It's given to the speech engine as a hint. |
| Heard as | Mishearings in quotes, replaced by the term automatically. List only forms that are never meant literally. Up to 10 per term. |
| Hint | Optional. always gives the term as a hint in every dictation. |
| Notes | For people. Ignored by dictation. |
A row with a problem is skipped, and the rest of the file is still read. Several vocabularies are combined in the order they're assigned.
Where artifacts are written
When central configuration is set up, Knowledge Worker Agent clears and rewrites one folder at each start:
OPENCODE_CONFIG_DIR. It never writes to the user's own opencode configuration, ~/.config/opencode. opencode combines the two, and where both set the same key, the assigned value wins. Instructions are the exception: assigned context is added to the user's own instructions, not put in their place.