Agent Toolkits & Skills
Cloud Harness MCP allows callers to dynamically configure and pre-install third-party agent toolkits upon opening a workspace. Toolkits provide pre-packaged agent instructions, workflows, and tools that AI collaborators can discover and run via skills_list, skills_read, and skills_run.
Supported Presets
Cloud Harness supports curated open-source toolkit presets whose normalized bundles are content-addressed upon acquisition (an explicit version can be specified for deterministic pinning):
| Preset ID | Name | Description | Default Scope |
|---|---|---|---|
mattpocock/skills | Matt Pocock Skills | 53 software engineering skills including TDD, bug diagnosis, and codebase architecture. | owner |
obra/superpowers | Superpowers | Agentic skills framework and session-start tool mapping instructions. | owner |
Using a Preset
Pass the preset inside the toolkits array during workspace_open:
{
"repositoryUrl": "https://github.com/my-org/my-project.git",
"idempotencyKey": "unique-session-key-001",
"toolkits": [
{
"kind": "preset",
"id": "mattpocock/skills",
"scope": "owner"
},
{
"kind": "preset",
"id": "obra/superpowers",
"scope": "owner"
}
]
}Custom Git Toolkits
You can load skills from any public HTTPS Git repository belonging to ALLOWED_GIT_HOSTS by specifying kind: "git":
{
"repositoryUrl": "https://github.com/my-org/my-project.git",
"idempotencyKey": "unique-session-key-002",
"toolkits": [
{
"kind": "git",
"instanceId": "team-skills",
"url": "https://github.com/my-org/custom-agent-skills.git",
"ref": "7b84a9e2d31c0e48a12f5a6b7c8d9e0f1a2b3c4d",
"scope": "owner",
"layout": {
"skillRoots": ["skills", "custom/workflows"],
"recursive": true
}
}
]
}Git Toolkit Options
instanceId(required): Unique alphanumeric identifier (1–80 chars) for this toolkit instance.url(required): HTTPS repository URL (must belong toALLOWED_GIT_HOSTS).ref(optional): Exact 40-character SHA-1 or 64-character SHA-256 commit hash object ID. Omit to target the repository's defaultHEAD.subdirectory(optional): Relative path within the repository to scope skill discovery.layout.skillRoots(optional): Relative subdirectories to search for skills. Defaults to['skills'].layout.recursive(optional): Recursively discover nestedSKILL.mddirectories. Defaults totrue.skills.include/skills.exclude(optional): Filter specific skill names to include or omit.
Licensed AgentKit Kits
Operator instances that hold an AgentKit licence can mount licensed kit skills (such as the engineer kit) directly, without publishing them as a public Git repository:
{
"repositoryUrl": "https://github.com/my-org/my-project.git",
"idempotencyKey": "unique-session-key-004",
"toolkits": [
{
"kind": "agentkit",
"kitId": "engineer",
"channel": "stable"
}
]
}AgentKit Kit Options
kitId(required): Licensed kit to mount. Supported:engineer,marketing.channel(optional): Release channel —stable(default),beta, ordev.version(optional): Exact semantic version to pin, for example2.17.0-beta.10. Omit to take the newest release on the channel.instanceId(optional): Caller-assigned instance name, when you mount the same kit on two channels.scope: Alwaysowner. Licensed content is mounted read-only and is never written into your repository.skills.include/skills.exclude(optional): Filter specific skill names to include or omit.
Prerequisites are operator-owned: the instance must pin the registry signing key (AGENTKIT_REGISTRY_KEY_ID and AGENTKIT_REGISTRY_PUBLIC_KEY), and each caller needs an AgentKit licence token stored as a provisioning-purpose global secret (default name AGENTKIT_REGISTRY_TOKEN, overridable with AGENTKIT_REGISTRY_CREDENTIAL_SECRET). A runtime-purpose token is refused, because runtime secrets are injected into executor environments and the licence token must never be readable by repository code. Without a usable secret, workspace_open fails closed and names the missing setting. A beta/dev mount also reports a warning in the toolkit lock so pre-release content is visible in the result.
Discoverability
GET /api/v1/toolkits (the dashboard's toolkits_list operation) returns the curated presets under toolkits and the licensed kits under licensedKits. Each licensed entry carries the exact selection to send, its default channel, available (instance key material configured) and credentialReady (this principal has the licence secret) plus requiresCredentialSecret, so a client can show why a kit is not usable yet without ever seeing a credential value. The remaining agent entry point is workspace_open itself.
The runner verifies the Ed25519 manifest signature and the package SHA-256 from that signed manifest before projecting any skill, and refuses to unpack a package that is not a single kit root. Skills then appear through skills_list, skills_read, and skills_run exactly like any other toolkit.
AgentKit CLI in the executor
The shipped executor includes a pinned beta of the ak CLI separately from the kit's read-only skill files. Reading ak-plan provides instructions; run its CLI commands through exec_run with the project working directory. Start with ak --version and ak plan --help. Local plan creation and validation do not require an AgentKit login, a kit install, or executor egress.
The CLI version and archive checksums are maintained in docker/executor.Dockerfile; the skill's version is not the CLI's version. AgentKit's own licence applies to the binary. The harness never copies the kit registry credential into the executor.
After an operator upgrades the executor image, open a new workspace to use it. If an older workspace reports ak: command not found, preserve its work before closing it; reconnecting ChatGPT alone does not replace its container. Custom executor images and local stdio installations must supply ak separately.
Operator-Provided Skills (built-in tier)
An operator can make skills available to every workspace on an instance without any toolkit selection, registry account, or entitlement. Point BUILTIN_SKILLS_ROOT at a host directory and upload skills into it:
# On the VPS, as root
sudo install -d -m 0755 /var/lib/cloud-harness/skills
sudo rsync -a --delete skills/ /var/lib/cloud-harness/skills/
find /var/lib/cloud-harness/skills -name SKILL.md | wc -lThen set BUILTIN_SKILLS_ROOT=/var/lib/cloud-harness/skills in the runner environment (/etc/cloud-harness-mcp/runtime.env) and restart the stack.
- The directory is mounted read-only into every executor at
/opt/cloud-harness/skills, the highest-precedence tier, so it outranks owner, workspace, and repository skills of the same name. skills_listreports these asbuilt-inwith trusttrusted-control-plane.- The harness never writes to the directory, and it is not copied into the toolkit cache, so updating skills is a plain file upload.
- Skill scripts remain runnable through
skills_run, which still requires the caller to pin the digest returned byskills_list. BUILTIN_SKILLS_ROOTis a reserved name: a workspace can never set it as a secret or environment value, so project content cannot shadow your catalog. If the runner rejects a stored record with that name on upgrade, delete it withsecret_delete(deletion of a reserved name stays allowed) and reopen.- The former
CH_BUILTIN_SKILLS_ROOToverride is no longer read. Rename that variable toBUILTIN_SKILLS_ROOT, or move the catalog to the mount target. - A container created before this change keeps its old environment until it is closed or rebuilt, so close or let pre-upgrade workspaces expire before relying on the tier being operator-only.
Use this for your own or licensed content that lives on your host. Use { "kind": "agentkit" } instead when the content must come from a signed AgentKit registry release, and a git toolkit when it comes from a public repository.
Installation Scopes: owner vs workspace
Cloud Harness supports two installation scopes depending on your workflow needs:
1. owner Scope (Default & Recommended)
- Mount Path:
/opt/cloud-harness/owner-skills:ro - Isolation: Mounted as a kernel-enforced read-only volume (
:ro) into the executor. - Clean Git Status: Does not create or modify files inside the project working tree (
/workspace), leavinggit status --porcelaincompletely clean. - Immutability: Processes running inside the container cannot alter or delete owner-mounted skills.
2. workspace Scope
- Materialization Path:
.cloud-harness/skills/ - Confirmation Flag: Requires setting
"allowToolkitWorkspaceChanges": trueinworkspace_open. - Committed Files: Staged directly into the project working tree, allowing skills to be inspected, modified, and committed to version control alongside application code.
- Conflict Prevention: If a skill with the same name already exists in the target directory with conflicting content,
workspace_openfails with aCONFLICT(409) error.
{
"repositoryUrl": "https://github.com/my-org/my-project.git",
"idempotencyKey": "unique-session-key-003",
"toolkits": [
{
"kind": "preset",
"id": "mattpocock/skills",
"scope": "workspace"
}
],
"allowToolkitWorkspaceChanges": true
}4-Tier Skill Precedence
When tools query available skills via skills_list or skills_read, Cloud Harness resolves name collisions using a deterministic 4-tier precedence hierarchy:
Rank 4 (Highest): built-in (/opt/cloud-harness/skills:ro)
Rank 3: owner (/opt/cloud-harness/owner-skills:ro)
Rank 2: workspace (/workspace/.cloud-harness/skills)
Rank 1 (Lowest): repository (/workspace/.agents/skills or .claude/skills)- Higher-rank skills take precedence over lower-rank skills of the same name.
skills_listreports shadowed candidates undershadowedmetadata.- Same-tier collisions (e.g. two owner toolkits declaring conflicting
deployskills) fail deterministically withCONFLICT(409). - The dashboard's Skills & Skill Sets page manages the library, imports, sets, and the registry, and settles a launch conflict with an operator override instead of guessing.
Skills over MCP (native client skills)
The HTTP /mcp endpoint also implements the official MCP Skills extension (io.modelcontextprotocol/skills, SEP-2640) for clients on protocol revision 2026-07-28. A client that supports it can discover and read skills with skills/list, skills/get, and resources/read, without opening a workspace.
| Skills exposed over MCP | Host activates a skill | |
|---|---|---|
| Who acts | Cloud Harness serves skill files | Your AI client (the host) |
| What happens | Lists skills and returns file bytes, each pinned to a SHA-256 digest and size | Verifies the bytes, asks for your approval if required, and loads the instructions into the model's context |
| Runs code? | Never | Only through the host's own approval; Cloud Harness scripts still run only through skills_run with its digest pin and privilege grant |
What is served:
built-inskills and your own enabled library skills (theownertier). Another user's skills are never visible.- Workspace and repository skills are served only when the client connects to the workspace-bound endpoint
/mcp/workspaces/<workspaceId>for one of your open workspaces. It adds that workspace'sworkspacetier (.cloud-harness/skills, where workspace toolkits passed toworkspace_openare applied) andrepositorytier (.agents/skills,.codex/skills,.claude/skills), read from its checkout. Repository skills are whatever the repository contains: treat them as untrusted. A workspace or repository skill is served only when its directory name matches thenamein its frontmatter, and at most 60 skill directories per skill folder are considered. Once the workspace is closed or its lease expires, the next request to the endpoint is refused. Owner-scope toolkits passed toworkspace_openare not served over the extension; useskills_list/skills_readon the open workspace for those. - Each file has a URI of the form
skill://cloud-harness/<tier>/<name>/<file>, orskill://cloud-harness/<tier>/<workspaceId>/<name>/<file>for theworkspaceandrepositorytiers. A skill is limited to 512 files and 16 MiB; larger skills, and any skill containing a symbolic link, are omitted, never served partially. - Directory reads (
resources/directory/read) are not supported; the per-skill file manifest lists every file instead.resources/listis intentionally empty, so discover skills withskills/list.
Clients without the extension, local stdio mode, and the /mcp-gateway endpoint see no change: keep using the skills_list, skills_read, and skills_run tools. See the Troubleshooting page if a skill is missing.
Storage & Provisioning Security
- Runner Content-Addressed Storage (CAS): Normalized skill bundles are cached under
TOOLKIT_CACHE_ROOTusing full-tree SHA-256 digests. Warm workspace starts reuse cached bundles with zero network egress. - Universal Provisioning Firewall: Helper containers used to clone and normalize toolkits run attached strictly to an internal Docker network (
internal: true). All outbound egress routes throughprovisioning-proxy:3128, enforcing DNS allowlists and blocking private subnets and cloud metadata (169.254.169.254). - Staging Containment: All staged paths are validated to prevent relative symlink escapes (
..), enforcing strict file count and byte ceilings before publication.