Agents, skills & teams API
CRUD for agents, skills, and teams stored in Kumiho, with avatars and kref semantics.
This page documents the gateway endpoints that manage your agent roster, skill library, and teams — the building blocks the dashboard’s Agents, Skills, and Teams pages create and edit. All three are persisted in Kumiho graph memory, so a definition created through the API survives daemon restarts and is referenceable from workflow YAML.
Use these endpoints when you want to script the registry instead of clicking through the dashboard: bulk-import agents, sync skills from your own source, or wire team topologies into a deployment pipeline. For the dashboard equivalents, see Agents, teams & canvas and Skills, tools & integrations pages. For the conceptual model behind agents, teams, and swarms, see Agents, teams & swarms.
Authentication
Section titled “Authentication”Every route on this page requires the pairing bearer token:
Authorization: Bearer <token>Obtain the token through the pairing flow described in Pairing & authentication. A missing or invalid token returns 401. Requests share the gateway’s default 64 KiB JSON body cap and request timeout, except the avatar upload routes, which are documented separately below.
How storage works
Section titled “How storage works”Agents, skills, and teams are not stored in config.toml. They live in Kumiho as items, revisions, and (for teams) bundles. Two Kumiho projects are used, both configurable under [kumiho]:
| Resource | Kumiho project (config key) | Default project | Space |
|---|---|---|---|
| Agents | kumiho.harness_project | Revka | AgentPool |
| Teams | kumiho.harness_project | Revka | Teams |
| Skills | kumiho.memory_project | CognitiveMemory | Skills |
The full space path is /{project}/{space} — for example /Revka/AgentPool or /CognitiveMemory/Skills. The gateway creates the project and space lazily on first write, so you do not need to provision them in advance.
For each resource:
- The item (or bundle, for teams) is the stable identity. Its name is a slug.
- The latest published revision holds the editable metadata (identity, description, member counts, and so on).
- An artifact holds heavier payloads — avatar image bytes, or a skill’s full markdown — referenced by a
file://location on disk.
Each write creates a new revision and tags it published, so history is preserved and never overwritten in place. See Graph model: spaces, items & provenance for the underlying model.
The kref format
Section titled “The kref format”A kref (kref://…) is the canonical pointer to a Kumiho entity. Items use this shape:
kref://<Project>/<Space>/<slug>.<suffix>Examples:
kref://Revka/AgentPool/senior-rust-engineer.agentkref://CognitiveMemory/Skills/debugging-skills.skillkref://Revka/Teams/platform-teamThe slug is derived from the supplied name by lowercasing, replacing every non-alphanumeric character with a hyphen, and collapsing repeats — so "Senior Rust Engineer" becomes senior-rust-engineer. This slug is exactly the value workflow YAML expects in assign: (agents) and team: (teams), which is why responses return it separately as item_name, distinct from the human-readable name.
Revision krefs add selectors, e.g. kref://Revka/AgentPool/senior-rust-engineer.agent?r=3&a=SKILL.md. When you pass a kref in a URL path, the agent and team routes strip and re-add the kref:// prefix for you, so both kref://Revka/... and Revka/... work in the {*kref} path segment. The skill detail, update, and delete routes do not perform this normalization — for those routes, omit the kref:// prefix and pass the path segment directly (e.g. CognitiveMemory/Skills/debugging-skills.skill).
Agent management
Section titled “Agent management”Agents are Kumiho items of kind agent in the AgentPool space. Each carries identity, soul, expertise, tone, role, type, an optional model override, and an optional system hint.
Endpoints
Section titled “Endpoints”GET /api/agentsPOST /api/agentsPUT /api/agents/{*kref}DELETE /api/agents/{*kref}POST /api/agents/deprecatePOST /api/agents/avatarList agents
Section titled “List agents”GET /api/agents?include_deprecated=false&q=rust&page=1&per_page=9Authorization: Bearer <token>| Query param | Type | Default | Meaning |
|---|---|---|---|
include_deprecated | bool | false | Include disabled agents in the result. |
q | string | — | Full-text search. When present, uses Kumiho search instead of a plain list. |
page | int | 1 | 1-based page number. |
per_page | int | 9 | Items per page. Clamped to the range 1–50. |
Response:
{ "agents": [ { "kref": "kref://Revka/AgentPool/senior-rust-engineer.agent", "name": "Senior Rust Engineer", "item_name": "senior-rust-engineer", "kind": "agent", "deprecated": false, "created_at": "2026-06-18T00:00:00Z", "identity": "...", "soul": "...", "expertise": ["Rust", "async"], "tone": "direct", "role": "engineer", "agent_type": "specialist", "model": "claude-opus-4", "system_hint": "...", "revision": 3, "revision_number": 3, "avatar_url": "/workspace/...?sig=...&expires=...", "avatar_artifact_name": "profile-avatar", "avatar_filename": "headshot.png", "avatar_mime": "image/png" } ], "total_count": 1, "page": 1, "per_page": 9}Non-search list responses are served from a 3-second in-process cache to absorb rapid dashboard polling. The cache is invalidated on every write.
Create an agent
Section titled “Create an agent”POST /api/agentsAuthorization: Bearer <token>Content-Type: application/json{ "name": "Senior Rust Engineer", "identity": "A pragmatic systems engineer.", "soul": "Calm, precise, allergic to overengineering.", "expertise": ["Rust", "async", "tokio"], "tone": "direct", "role": "engineer", "agent_type": "specialist", "model": "claude-opus-4", "system_hint": "Prefer the smallest correct change."}name, identity, and soul are required; the rest are optional. On success the endpoint returns 201 Created with { "agent": { ... } }. It slugifies name into the item identifier, writes a revision holding the metadata, and tags that revision published.
Update an agent
Section titled “Update an agent”PUT /api/agents/kref://Revka/AgentPool/senior-rust-engineer.agentAuthorization: Bearer <token>Content-Type: application/jsonThe body is the same shape as create. An update writes a new revision (it does not edit the old one) and re-tags it published. Any existing avatar metadata is preserved across the update, so editing fields does not drop the agent’s avatar.
Deprecate an agent
Section titled “Deprecate an agent”POST /api/agents/deprecateAuthorization: Bearer <token>Content-Type: application/json
{ "kref": "kref://Revka/AgentPool/senior-rust-engineer.agent", "deprecated": true }Deprecation is a soft toggle. Deprecated agents are hidden from the default list but reappear when you pass include_deprecated=true. Set "deprecated": false to re-enable.
Delete an agent
Section titled “Delete an agent”DELETE /api/agents/kref://Revka/AgentPool/senior-rust-engineer.agentAuthorization: Bearer <token>Returns 204 No Content. This permanently removes the item; prefer deprecation when you only want to disable an agent.
Skill management
Section titled “Skill management”Skills are Kumiho items of kind skill in the Skills space. A skill is a markdown document plus lightweight metadata. To keep list responses small, the gateway splits storage in two:
- Revision metadata holds only
description,domain,tags, andcreated_by. - The full markdown is written to
~/.revka/workspace/skills/<slug>.mdand referenced by aSKILL.mdartifact whoselocationis afile://URI. Content is read from disk on demand for detail views and edits.
Endpoints
Section titled “Endpoints”GET /api/skillsPOST /api/skillsGET /api/skills/{*kref}PUT /api/skills/{*kref}DELETE /api/skills/{*kref}POST /api/skills/deprecateList skills
Section titled “List skills”GET /api/skills?include_deprecated=false&q=debug&page=1&per_page=9Authorization: Bearer <token>Query params match the agents list (include_deprecated, q, page, per_page; per_page clamped to 1–50). List responses omit full content — the content field is empty (or a 200-character preview for legacy skills that stored content inline) to keep payloads under Kumiho’s gRPC limit. Use the detail endpoint to read the full markdown. Search resolves both the current skill kind and the legacy skilldef kind. Non-search results are cached for 30 seconds.
{ "skills": [ { "kref": "kref://CognitiveMemory/Skills/debugging-skills.skill", "name": "debugging-skills", "item_name": "debugging-skills", "deprecated": false, "created_at": "2026-06-18T00:00:00Z", "description": "Systematic debugging workflow", "content": "", "domain": "engineering", "tags": ["debug"], "revision_number": 2 } ], "total_count": 1, "page": 1, "per_page": 9}Get one skill (with content)
Section titled “Get one skill (with content)”GET /api/skills/kref://CognitiveMemory/Skills/debugging-skills.skillAuthorization: Bearer <token>Returns { "skill": { ... } } with the content field populated. Content is resolved in priority order: the local file via the artifact location, then artifact metadata, then revision metadata (the latter two cover ClawHub and very old installs).
Create a skill
Section titled “Create a skill”POST /api/skillsAuthorization: Bearer <token>Content-Type: application/json{ "name": "Debugging skills", "description": "Systematic debugging workflow", "content": "# Debugging\n\nReproduce, minimise, hypothesise...", "domain": "engineering", "tags": ["debug"]}name, description, content, and domain are required; tags is optional. The create flow slugifies name, writes the revision metadata, stores the markdown to disk as the SKILL.md artifact, then tags the revision published. Returns 201 Created.
Update a skill
Section titled “Update a skill”PUT /api/skills/kref://CognitiveMemory/Skills/debugging-skills.skillAuthorization: Bearer <token>Content-Type: application/jsonSame body as create. The update writes a new revision, rewrites the markdown file, attaches a fresh SKILL.md artifact, and re-publishes.
Deprecate and delete
Section titled “Deprecate and delete”POST /api/skills/deprecate Body: { "kref": "...", "deprecated": true }DELETE /api/skills/{*kref} Returns 204 No ContentDeprecation behaves like agents — a soft toggle controlling default-list visibility. Delete is permanent.
Team management
Section titled “Team management”Teams are Kumiho bundles in the Teams space. A bundle groups agent members; directed edges between members express the delegation topology. Edge types are REPORTS_TO, SUPPORTS, and DEPENDS_ON. A team can be referenced from workflow YAML’s team: field.
Endpoints
Section titled “Endpoints”GET /api/teamsPOST /api/teamsGET /api/teams/{*kref}PUT /api/teams/{*kref}DELETE /api/teams/{*kref}POST /api/teams/deprecatePOST /api/teams/avatarList teams
Section titled “List teams”GET /api/teams?include_deprecated=false&page=1&per_page=9Authorization: Bearer <token>| Query param | Type | Default | Meaning |
|---|---|---|---|
include_deprecated | bool | false | Include disabled teams. |
page | int | 1 | 1-based page number. |
per_page | int | 9 | Items per page. Clamped to 1–50. |
The list endpoint returns summary fields only (member_count, member_names, edge_count) from bundle metadata — it does not enrich each team with full member detail. Fetch a single team to get the resolved member and edge lists. Results are cached for 30 seconds.
Get one team
Section titled “Get one team”GET /api/teams/kref://Revka/Teams/platform-teamAuthorization: Bearer <token>Returns the full team with members and edges resolved:
{ "team": { "kref": "kref://Revka/Teams/platform-team", "name": "Platform Team", "description": "Owns the runtime and deploy pipeline.", "deprecated": false, "created_at": "2026-06-18T00:00:00Z", "members": [ { "kref": "kref://Revka/AgentPool/senior-rust-engineer.agent", "name": "senior-rust-engineer", "role": "engineer", "agent_type": "specialist", "identity": "...", "expertise": ["Rust"], "avatar_url": "/workspace/...?sig=..." } ], "edges": [ { "from_kref": "kref://Revka/AgentPool/junior.agent", "to_kref": "kref://Revka/AgentPool/senior-rust-engineer.agent", "edge_type": "REPORTS_TO" } ], "avatar_url": null, "avatar_artifact_name": null, "avatar_filename": null, "avatar_mime": null }}Create a team
Section titled “Create a team”POST /api/teamsAuthorization: Bearer <token>Content-Type: application/json{ "name": "Platform Team", "description": "Owns the runtime and deploy pipeline.", "members": [ "kref://Revka/AgentPool/senior-rust-engineer.agent", "kref://Revka/AgentPool/junior.agent" ], "edges": [ { "from_kref": "kref://Revka/AgentPool/junior.agent", "to_kref": "kref://Revka/AgentPool/senior-rust-engineer.agent", "edge_type": "REPORTS_TO" } ]}name is required; description, members (agent krefs), and edges are optional. The gateway creates the bundle, adds each member, and creates the edges. On success it returns 201 Created with the fully built team.
Edge validation
Section titled “Edge validation”Before persisting, the gateway validates the team graph and rejects an invalid one with 400 and a validation_errors array. The checks are:
| Code | Triggered when |
|---|---|
self_edge | An edge has the same from_kref and to_kref. |
dangling_ref | An edge endpoint is not in the members list. |
reciprocal_depends | Two DEPENDS_ON edges point both ways between the same pair. |
cycle | The execution edges (DEPENDS_ON, SUPPORTS, FEEDS_INTO) form a dependency cycle. |
{ "error": "Team graph is invalid", "validation_errors": [ { "code": "cycle", "message": "Dependency cycle detected among 2 member(s). ..." } ]}Update a team
Section titled “Update a team”PUT /api/teams/kref://Revka/Teams/platform-teamAuthorization: Bearer <token>Content-Type: application/jsonSame body as create. The update re-validates the graph, writes a new metadata revision, then reconciles state: it adds members that are newly listed, removes members that are gone, deletes all existing edges between members, and recreates the edges from the request. Existing avatar metadata is preserved.
Deprecate and delete
Section titled “Deprecate and delete”POST /api/teams/deprecate Body: { "kref": "...", "deprecated": true }DELETE /api/teams/{*kref} Returns 204 No Contentdeprecate returns { "success": true }. Delete first removes the edges between members and the bundle membership, then deletes the bundle itself.
Avatar upload
Section titled “Avatar upload”Agents and teams support an avatar image. Skills do not.
POST /api/agents/avatarPOST /api/teams/avatarAuthorization: Bearer <token>Content-Type: multipart/form-dataMultipart fields:
| Field | Required | Meaning |
|---|---|---|
kref | yes | The agent item kref or team bundle kref. |
file | yes | The image bytes. |
Constraints:
- Max size: 5 MiB per file. Larger uploads return
413 Payload Too Large. - Allowed formats: PNG, JPEG, and WebP, detected by content (magic bytes), not just the declared MIME type. SVG is explicitly rejected. An unsupported type returns
415 Unsupported Media Type. - These two routes run on a dedicated router with a 60-second timeout, separate from the gateway’s default JSON body cap.
On success the endpoint returns the updated agent or team object. The image bytes are written under the workspace directory (artifacts/<project>/<space>/<slug>/avatars/<uuid>.<ext>), recorded as a Kumiho artifact named profile-avatar, and the file path is stored in revision metadata. The returned avatar_url is an HMAC-signed, time-limited URL served from the workspace asset endpoint — agent avatar URLs are signed for 24 hours — so browsers can render the image without exposing arbitrary filesystem access. See TLS, rate limiting, WebAuthn & static serving for how signed workspace URLs work.
Example with curl:
curl -X POST https://<gateway>/api/agents/avatar \ -H "Authorization: Bearer $TOKEN" \ -F "kref=kref://Revka/AgentPool/senior-rust-engineer.agent" \Errors
Section titled “Errors”These routes share the gateway’s central Kumiho error mapping. A 404 from Kumiho on a list call is treated as “space not yet created” — the gateway provisions the project and space and returns an empty list rather than an error. Other upstream failures (including 5xx) are surfaced as a consistent gateway error shape, typically 503 with a kumiho_upstream_unavailable reason, so the dashboard renders one predictable error state.
Related pages
Section titled “Related pages”- Gateway API overview — transports, auth, and shared conventions.
- Workflows & Architect API — where agent slugs (
assign:) and team slugs (team:) are referenced. - Memory graph & Asset Browser API — the generic Kumiho read proxy and typed asset write routes.
- Agents, teams & swarms — the conceptual model.
- Kumiho graph memory — how Kumiho stores items, revisions, and bundles.