The capability system lets users and agents add skills, tools, workers (subagents), and MCP servers to a running SIM-ONE Alpha instance without rebuilding.
Built-in Flue runtime capabilities are source-time application code. Built-in Agent Skills live under src/skills/<name>/SKILL.md, are imported with with { type: 'skill' }, and are registered directly on the owning agent or workflow. Example: src/skills/greeting-preflight/SKILL.md is registered on src/agents/orchestrator.ts.
The capability registry is the post-build extension lane. Its default paths are
<runtime-root>/db/capabilities.sqlite and
<runtime-root>/capabilities/. GOROMBO_CAPABILITY_DB_PATH and
GOROMBO_CAPABILITIES_DIR can override them; relative overrides resolve under
the same canonical runtime root. GOROMBO_CAPABILITY_DIR remains a supported
fallback for the capability directory. The orchestrator reads the store at
agent init (createAgent(...)) and merges user-defined capabilities into the
same tools, skills, and subagents arrays that hold built-in capabilities.
A service restart picks up changes; no rebuild is needed.
Four capability kinds:
| Kind | Flue ingress | Runtime loading path |
|---|---|---|
| Skill | skills: [...] + auto-discovery of <cwd>/.agents/skills/<name>/ |
Built-ins import from src/skills. Registry/user skills materialize into the discovery path. Flue loads both natively. |
| Tool | tools: ToolDefinition[] |
Dynamic import() of user JS modules exporting defineTool(...) results. |
| Worker (subagent) | subagents: AgentProfile[] |
Dynamic import() of user JS modules exporting defineAgentProfile(...) results. |
| MCP | connectMcpServer(name, opts) -> { tools } |
connectMcpServer(...) per enabled row at init; tools spread into tools. |
User CLI request
-> sim-one command
-> applicable protocol bundle
-> shared lifecycle service
-> SQLite capabilities table
-> managed capability files
Agent lifecycle request
-> orchestrator and Protocol Tool
-> capability-manager
-> approval gate for mutations
-> shared lifecycle service
-> SQLite capabilities table
-> managed capability files
Capability implementation request
-> Coding Worker authoring skills and tools
-> protocol-routed classification, validation, scan, and tests
-> typed source handoff
-> capability-manager
-> Service restart
-> createAgent(...) init
-> loadUserCapabilities(env) reads SQLite
-> promoted managed packages are selected without refetching mutable sources
-> connectUserMcpServers() opens MCP connections
-> merge into tools/skills/subagents arrays
-> built-in + user capabilities live together
CREATE TABLE capabilities (
id TEXT NOT NULL,
kind TEXT NOT NULL, -- 'skill' | 'tool' | 'worker' | 'mcp'
name TEXT NOT NULL,
description TEXT NOT NULL,
source TEXT NOT NULL, -- 'github' | 'local' | 'npm' | 'builtin'
source_ref TEXT NOT NULL, -- URL | workspace-relative path | built-in ref
version TEXT,
enabled INTEGER NOT NULL DEFAULT 0,
config_json TEXT NOT NULL DEFAULT '{}',
installed_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
installed_by TEXT NOT NULL DEFAULT 'cli',
PRIMARY KEY (kind, id)
);
CREATE INDEX IF NOT EXISTS idx_capabilities_kind_enabled
ON capabilities(kind, enabled);
CREATE UNIQUE INDEX IF NOT EXISTS idx_capabilities_id_unique
ON capabilities(id);
SQLite is authoritative. A config-file mirror (gorombo.config.json capabilities section) reconciles into SQLite on boot.
The persisted source enum retains builtin and the legacy npm value for
registry compatibility. New lifecycle requests accept only github and
local; unsupported sources fail before materialization. A github source
must be a github.com HTTPS or SSH repository URL, so a local path or
file:// URL cannot cross that trust boundary. Agent-installed local sources
must be workspace-relative and resolve beneath <runtime-root>/workspace.
Authenticated CLI callers may also provide an absolute local source path.
The sim-one binary is the authenticated user interface for capability
management. Agent requests are delegated to the built-in
capability-manager; the orchestrator has no direct capability mutation tools.
A source checkout also includes scripts/capability-admin.mjs as a
compatibility adapter to sim-one. It contains no SQLite or materialization
implementation.
All three surfaces use CapabilityLifecycleService for list, inspect,
validate, add, update, enable, disable, and remove. Agent mutations require a
current matching approval. The capability manager accepts only the persisted
normalized message eventId as protocol context, reloads the applicable bundle
from the SQLite protocol provider, and rejects missing or mismatched event
state. It does not trust a model-authored protocol bundle. Direct CLI commands
are attributable to the authenticated user and do not accept model-supplied
identity.
Enabled capability records are read when the orchestrator initializes. After a lifecycle change, restart the gateway through the process or service manager that launched it. See the CLI Reference for executable product commands.
<configured-capability-directory>/
skills/<id>/SKILL.md + supporting files
tools/<id>/index.mjs
workers/<id>/index.mjs
The default is <runtime-root>/capabilities/.
GOROMBO_CAPABILITIES_DIR overrides it; relative overrides remain under the
same canonical root. GOROMBO_CAPABILITY_DIR is the fallback override.
Capabilities live outside the compiled server and survive upgrades.
src/engine/capabilities/
types.ts CapabilityRecord, CapabilityStore interfaces
capability-lifecycle-service.ts
shared validation, mutation, rollback, and result contract
capability-protocol-context.ts
fail-closed Protocol Tool bundle compiler
capability-store.ts SQLite CRUD
capability-loader.ts loadUserCapabilities(env) — reads SQLite, returns grouped by kind
skill-materializer.ts copies/github-clones sources into lifecycle staging directories
mcp-broker.ts connectUserMcpServers() — opens MCP connections, returns tools
index.ts barrel exports
scripts/
capability-admin.mjs compatibility adapter to the sim-one CLI
src/engine/workers/
capability-manager/ Flue lifecycle owner for agent requests
coding-worker/
capability-authoring/ scoped scaffold, validation, test, and handoff tools
skills/ imported capability authoring skills
src/agents/
orchestrator.ts Modified — calls loadUserCapabilitiesFromStore(env) at init,
merges user tools/MCP into tools array, user workers into subagents
Adding a capability writes to SQLite. When the gateway process restarts,
createAgent(...) initialization re-reads SQLite and loads only the promoted
managed package. It never recopies or reclones a mutable source during startup.
An enabled record whose promoted package is missing fails closed and is not
attached. No product rebuild is required.
User-defined capabilities live in SQLite and
<runtime-root>/capabilities/, outside the packaged application artifact.
Agent-added skills may be enabled inside the approved add transaction because they contain instructions and supporting content rather than executable code. Agent-added tools, workers, and MCP connections are installed disabled and require a separate approved enable operation before they can enter the runtime. Updating an executable tool, worker, or MCP connection also returns it to the disabled state; the changed capability requires a separate enable operation. Direct CLI actions use the authenticated user as the principal.
After enablement, executable capabilities remain subject to protocols, trusted scope, owning-agent attachment, sandbox policy, and action-specific approval requirements.
The capabilities.lifecycle-routing base protocol governs capability work.
Coding Worker classification, source validation, security scanning, tests,
packaging, and handoff require the applicable Protocol Tool bundle.
Capability-manager validation and every mutation require it as well.
These paths fail closed when the bundle is missing or malformed. Successful validation and handoff results include redacted protocol context with applied protocol ids and rules. Deterministic checks do not replace protocols; they run after protocol directives have been compiled. Source-backed validation uses a non-executing TypeScript syntax check for exported Flue factories and a shared package scan for credential values and machine-specific absolute paths.
The Coding Worker owns source development inside the selected
workspace/projects/<slug> or workspace/repos/<slug> target. It imports
Flue skills for capability design, skill authoring, tool authoring, worker
authoring, and MCP authoring. Its typed tools classify, approval-gate
scaffolding, validate contracts, scan for secrets and machine host paths, run
bounded tests, and prepare a content-digest-bound handoff.
A handoff requires passing test evidence for the current content digest and
protocol directives. Local approval metadata includes a SHA-256 source identity
instead of the private path itself, so an approval cannot be reused for a
different local source. Staging rejects symbolic links and verifies
sha256:<digest> handoffs against the exact materialized package before
promotion. Add and update approvals also include a canonical digest of the
complete lifecycle mutation payload, so changed names, descriptions, sources,
versions, activation requests, or MCP settings require a distinct approval.
Executable source files containing NUL bytes or invalid UTF-8 fail validation
instead of being skipped as binary package assets.
MCP connection handoffs carry the validated endpoint, transport, and optional
canonical token configuration key. Supported token slots are
GOROMBO_MCP_TOKEN, MCP_AUTH_TOKEN, and MCP_TOKEN; lifecycle validation
rejects any other key before the record can be enabled. Partial MCP updates
merge defined fields with the stored connection before validation, so changing
transport or token configuration does not discard the endpoint.
Executable package validation accepts only direct exported
defineTool(...) or defineAgentProfile(...) results, including arrays made
entirely from direct results. A function that merely contains a factory call
is not a loadable Flue capability and is rejected before promotion.
The Coding Worker never imports the capability store, lifecycle service, materializer, or managed capability path resolver.
gorombo.config.json has a capabilities array that reconciles into SQLite on boot (in src/db.ts, at server startup — before any agent request). Config is additive: entries in config but missing from SQLite get inserted with installedBy: "seed"; entries already in SQLite are skipped (idempotent). Reconciliation does not fetch or copy source bytes at startup; an enabled source-backed record is attached only when its promoted managed package already exists. Removal is a CLI/db operation, not a config edit.
{
"version": 1,
"models": { "primary": "..." },
"capabilities": [
{
"id": "my-skill",
"kind": "skill",
"name": "My Skill",
"description": "...",
"source": "github",
"sourceRef": "https://github.com/user/my-skill",
"enabled": true
}
]
}