# Step 7: Skills (Private Beta) Skills are folders an agent discovers, fetches, and runs at runtime. A skill is a directory with a `SKILL.md` (YAML frontmatter for `name` + `description`) plus any helper files the author shipped — Python, shell, configs, prompts, examples. The agent fetches the entire folder and its runtime decides what to do with it. Two ways to use Skills: - **REST endpoints** under `/v1/platforms/{platform_id}/skills/*` — for backends that want to drive search/fetch/review flows directly. - **MCP tools** — five tools (`find_skill`, `fetch_skill`, `create_skill`, `delete_skill`, `submit_skill_review`) auto-register on the MCP URL when `platform.skills_enabled = true`. An MCP-using agent doesn't need any custom integration code beyond provisioning. ``` ASSISTIV_API_BASE = https://api.assistiv.ai (Python API — REST endpoints) ASSISTIV_MCP_BASE = https://mcp.assistiv.ai (MCP service — tool execution) ``` --- ## Prerequisites: Admin Provisioning **Skills is admin-provisioned. Self-serve is not available in private beta.** All five REST endpoints and the five MCP tools return `403 forbidden` unless an Assistiv admin has flipped `platform.skills_enabled = true` on your platform. Email `founders@assistiv.ai` to request provisioning. Once enabled: - REST endpoints become callable with any `sk-plat_*` or `sk-eu_*` key on your platform. - The five MCP tools appear automatically in the tool list on the next MCP session (no SDK upgrade, no config change on your side). --- ## Storage Model There are two kinds of skills, fetched through the same endpoints: **Public skills** — synced from admin-vetted GitHub repos. A sweeper clones each repo every ~30 seconds, walks every `SKILL.md`, content-hashes the folder, dedupes byte-identical copies (so plugin-bundle repos that ship the same skill in three places collapse to one row), and indexes for hybrid search. Updates land within ~30 seconds of a commit to the source repo. You cannot register source repos via API — that's an admin action on the website. **Private skills** — uploaded by your platform via `POST /skills`. Files are inlined as base64, encrypted at rest in GCS. Ownership depends on which key created them: - `sk-plat_*` → owned by `platform_id`. Anyone on your platform with a platform key can manage it. - `sk-eu_*` → owned by the `end_user_id`. Survives API key rotation. Only that end user (or your platform's admin) can delete it. --- ## REST Endpoints All under `https://api.assistiv.ai/v1/platforms/{platform_id}/skills`: | Method | Path | Auth | Purpose | |---|---|---|---| | GET | `/search` | sk-plat_ or sk-eu_ | Hybrid retrieval (BM25 + pgvector + RRF). Query params: `query`, `top_k` (default 10, max 50), `visibility` (public/private/all). Returns matches with summaries, review aggregates, and recent comments. | | GET | `/{skill_id}` | sk-plat_ or sk-eu_ | Returns the full skill folder (multi-file, base64). Optional query params: `target_path` (string — when set, the response includes a plain-language `instruction` telling the agent runtime where to write files), `wrap_in_folder` (default true), `force` (default false). | | POST | `` | sk-plat_ or sk-eu_ | Mints a private skill. Body: `{ name, description, files: [{path, content_base64}], idempotency_key? }`. 1–200 files, max 5 MB each. Path traversal rejected. Returns 201 with `{skill_id, queued_at}`. Embedding generates in background — fetchable immediately, vector-searchable in seconds. | | DELETE | `/{skill_id}` | owner only | Soft-delete. Subsequent fetch returns 410. Public skills cannot be deleted via this endpoint (returns 403; admin-only takedown is internal). | | POST | `/{skill_id}/reviews` | sk-eu_ only | Submit a 4-dim review. Body: `{ rating_accuracy, rating_value, rating_efficiency, rating_clarity }` each 1–5, plus optional `comment` (max 2000 chars). One review per (skill, end-user); resubmits overwrite. Aggregates refresh atomically. | ### Folder size caps - 20 MB total per skill folder (returned inlined as base64). - 5 MB max per file. - 200 files max per folder. Exceeding any of these on `POST /skills` returns 422. Exceeding on `GET /skills/{id}` returns 413 (rare; usually means a vendored binary). --- ## Quality Model There is no LLM judge. Quality comes from agent-submitted reviews along four fixed dimensions: - **accuracy** — did it do what its SKILL.md said it would? - **value** — was the result useful for the agent's goal? - **efficiency** — tokens, time, side effects within reason? - **clarity** — was SKILL.md clear enough on the first try? Each dimension is 1–5. The `find_skill` ranker scores each match as ``` rrf_score × (1 + REVIEW_BOOST × normalized_rating × log(review_count + 1)) ``` Well-reviewed skills boost on the next search but new skills are never punished — they just don't get the bonus until they have reviews. Reviews are end-user-only. Platform keys (`sk-plat_*`) cannot submit reviews. This is intentional: reviews represent agent runtime experience, not platform opinion. --- ## MCP Tools (auto-registered when `skills_enabled = true`) Once your platform is provisioned, the mcp-service registers five tools on every per-user MCP session: - `find_skill(query, top_k?, visibility?)` — wraps `GET /skills/search`. - `fetch_skill(skill_id, target_path?, wrap_in_folder?, force?)` — wraps `GET /skills/{id}`. - `create_skill(name, description, files)` — wraps `POST /skills`. - `delete_skill(skill_id)` — wraps `DELETE /skills/{id}`. Soft-deletes a private skill you own. Free (does not count against the per-month skill-call quota). - `submit_skill_review(skill_id, rating_accuracy, rating_value, rating_efficiency, rating_clarity, comment?)` — wraps `POST /skills/{id}/reviews`. These appear automatically when an agent fetches its tool list. No extra configuration is needed. ### Two MCP URLs Both expose the same five tools and use the same billing/free tier. Pick by agent needs: - `POST https://mcp.assistiv.ai/mcp/skills` — scoped URL that returns ONLY the five skill tools. No `list_apps`, no per-app tools. Use this when the agent only needs skills (cleaner tool list, smaller prompt tax). - `POST https://mcp.assistiv.ai/mcp` — dynamic URL that returns skills ALONGSIDE every other MCP tool the end user has connected (GitHub, Slack, Zendesk, Zoho Mail). Use this when an agent mixes skills with other apps. Both require an end-user key (`sk-eu_*`). The `skills_enabled` gate, billing, and free tier are identical across both — only the tool list differs. See `https://www.assistiv.ai/docs/skills/mcp` for the three-call curl quickstart (initialize → tools/list → tools/call find_skill). --- ## Pricing & Free Tier First **5,000 skill calls per platform per calendar month are free**. The counter combines `find_skill`, `fetch_skill`, `create_skill`, and `submit_skill_review`. `delete_skill` is always free and never debits. After 5,000 calls: **$0.0004 per call ($0.40 per 1k)** — about 2.5× cheaper than the MCP tool-call rate because search and FS reads are simpler to serve than tool execution. The rate is flat regardless of skill folder size. Folder size is set by the source repo (admin-vetted GitHub or your own private upload), not by the caller, so fetching a 5 MB skill costs the same per call as fetching a 50 KB one. Inside the free tier: no wallet debit and no log row. Counter resets on the 1st of each month. Scale tier negotiates the rate and adds a dedicated catalog mirror for sustained 100M+ calls/month. --- ## Minimal Usage Example (TypeScript) Assumes `platform.skills_enabled = true` and the end user is provisioned. ```typescript const API_BASE = "https://api.assistiv.ai/v1"; const PLATFORM_ID = process.env.ASSISTIV_PLATFORM_ID!; const END_USER_KEY = "sk-eu_..."; // from your DB, keyed by your user's ID // 1. Search for a skill const search = await fetch( `${API_BASE}/platforms/${PLATFORM_ID}/skills/search?query=summarize+pdfs&top_k=5`, { headers: { Authorization: `Bearer ${END_USER_KEY}` } } ); const { matches } = await search.json(); const top = matches[0]; // 2. Fetch the full skill folder. Pass target_path to get a runtime instruction. const fetchRes = await fetch( `${API_BASE}/platforms/${PLATFORM_ID}/skills/${top.skill_id}?target_path=./workspace`, { headers: { Authorization: `Bearer ${END_USER_KEY}` } } ); const skill = await fetchRes.json(); // skill.files = [{ path, content_base64 }, ...] — every file in the folder // skill.instruction = plain-language directive for the agent runtime // 3. After running the skill, submit a 4-dim review (end-user key only) await fetch( `${API_BASE}/platforms/${PLATFORM_ID}/skills/${top.skill_id}/reviews`, { method: "POST", headers: { Authorization: `Bearer ${END_USER_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ rating_accuracy: 5, rating_value: 4, rating_efficiency: 4, rating_clarity: 5, comment: "Worked first try on a 30-page PDF.", }), } ); ``` For an MCP-using agent the same flow happens automatically — the model calls `find_skill`, then `fetch_skill`, then runs whatever the runtime materialized, then calls `submit_skill_review`. No custom integration code needed beyond admin provisioning. --- ## Minimal Usage Example (Python) ```python import os import requests API_BASE = "https://api.assistiv.ai/v1" PLATFORM_ID = os.environ["ASSISTIV_PLATFORM_ID"] END_USER_KEY = "sk-eu_..." # from your DB eu_headers = {"Authorization": f"Bearer {END_USER_KEY}"} # 1. Search search = requests.get( f"{API_BASE}/platforms/{PLATFORM_ID}/skills/search", headers=eu_headers, params={"query": "summarize pdfs", "top_k": 5}, ).json() top = search["matches"][0] # 2. Fetch full folder + runtime instruction skill = requests.get( f"{API_BASE}/platforms/{PLATFORM_ID}/skills/{top['skill_id']}", headers=eu_headers, params={"target_path": "./workspace"}, ).json() # skill["files"] = [{path, content_base64}, ...] # skill["instruction"] = plain-language directive for the runtime # 3. Review after running (end-user key only) requests.post( f"{API_BASE}/platforms/{PLATFORM_ID}/skills/{top['skill_id']}/reviews", headers={**eu_headers, "Content-Type": "application/json"}, json={ "rating_accuracy": 5, "rating_value": 4, "rating_efficiency": 4, "rating_clarity": 5, "comment": "Worked first try on a 30-page PDF.", }, ) ``` --- ## Common Failures | Symptom | Likely cause | First thing to check | |---|---|---| | `403 forbidden` on any `/skills/*` endpoint or skills MCP tool | `platform.skills_enabled = false` (admin not yet provisioned) | Email `founders@assistiv.ai`. Self-serve provisioning is not available in private beta. | | `404 not_found` on `GET /skills/{id}` after a successful create | Embedding still generating in background, or wrong `skill_id` | Wait a few seconds and retry. Vector search lags BM25 by ~5s on a fresh skill. Confirm `skill_id` matches what `POST /skills` returned. | | `410 gone` on `GET /skills/{id}` | Skill was soft-deleted by its owner | Distinct from 404. The row exists with `is_deleted=true`; rolling back requires admin action. | | `502 bad_gateway` on `GET /skills/{id}` (public skill) | Local sync clone missing on disk (sweeper recovering or pod restarted mid-sync) | Wait ~30s for the next sweep iteration and retry. Persists past 2 sweeps → sweeper is stuck; check `/healthz`. | | `413 payload_too_large` on `GET /skills/{id}` | Folder exceeds 20 MB inlined (rare; usually a vendored binary) | Author needs to trim the folder. Files >5 MB are also rejected at create time. | | Skills MCP tools don't appear in agent's tool list | `platform.skills_enabled = false` (most common), or stale MCP URL cached before provisioning | Provision the platform, then refetch `/v1/me/mcp-config`. Tools auto-register at session creation. | | `find_skill` returns the same skill at 7 different paths | Old DB state from before content_sha dedupe was deployed | Toggle the source repo's `is_active` flag in admin dashboard to force a re-sync. Sync collapses duplicates to one row. | | Submit review returns 403 with a `sk-plat_*` key | Reviews are end-user-only | Use a `sk-eu_*` key. Platform keys cannot submit reviews. | --- ## Reference - [Skills overview](https://www.assistiv.ai/docs/skills) — concepts, storage model, ranking, ownership. - [Skills MCP](https://www.assistiv.ai/docs/skills/mcp) — agent-side curl quickstart and tool reference. - [Skills API reference](https://www.assistiv.ai/docs/api-reference/skills) — endpoint-by-endpoint spec. - Integration index: [llms-full.txt](https://www.assistiv.ai/llms-full.txt) (search "Skills (private beta)" for the inline section).