Skip to content

feat(appkit): Agent Skills (v1) — SKILL.md progressive disclosure for agents - #532

Draft
MarioCadenas wants to merge 9 commits into
mainfrom
feat/agent-skills
Draft

feat(appkit): Agent Skills (v1) — SKILL.md progressive disclosure for agents#532
MarioCadenas wants to merge 9 commits into
mainfrom
feat/agent-skills

Conversation

@MarioCadenas

Copy link
Copy Markdown
Collaborator

Agent Skills (v1)

Runtime Agent Skills for the agents plugin — the SKILL.md format Claude Code / Cursor use, brought to AppKit agents. Only each skill's name + description sit in the system prompt (always-on, cheap); the full body loads on demand. Works on any Databricks-served model — AppKit implements the progressive disclosure itself, so it doesn't depend on a provider-native skills feature. Fills the seam the loader already reserved (RESERVED_DIRS = new Set(["skills"])).

Not to be confused with the dev-time "Databricks Agent Skills" product (Claude Code skills for building apps) — this is a runtime capability of deployed agents.

What a skill is

A directory with a SKILL.md (frontmatter name + description, Markdown body) plus optional bundled reference files. Frontmatter is an Anthropic-format superset (also tolerates license, allowed-tools, metadata); unknown keys warn, not error — so skills authored elsewhere drop in.

How it works

  • Every visible skill's name + description is injected into the agent's system prompt.
  • Two read-only built-in tools are added to any agent with a catalog: load_skill(skill) returns the body + a manifest of bundled files; read_skill_file(skill, path) reads one of those files (through a directory-containment guard).
  • The model auto-loads a skill when a task matches; a user can force one for a turn with /skill-name in chat (or useAgentChat's send(msg, { skill })).

Sources & visibility

  • Global bundle config/agents/skills/, per-agent config/agents/<id>/skills/, and a catalog UC Volume (skillsVolume / DATABRICKS_VOLUME_AGENT_SKILLS), read as the service principal.
  • Per-agent skills are always visible; global skills are opt-in via skills: [...] frontmatter (or autoInheritSkills).
  • Name collisions resolve to qualified <scope>:name; the bare name errors as ambiguous.

Commits (phased, independently reviewable)

  1. feat(appkit): load and resolve agent skills from bundle sources — model, parser, loader, per-agent catalog resolution
  2. feat(appkit): expose skills to agents via prompt catalog and load_skill — disclosure + built-in tools (bundle e2e)
  3. feat(appkit): source agent skills from a Unity Catalog volume — catalog source, SP-read
  4. feat(appkit): let users load skills from chat (/skill-name + picker) — client UX + forced load
  5. feat(appkit): document agent skills, wire sub-agents, ship example skill
  • plus a plugin-catalog sync and two dev-playground commits (a haiku demo skill + a /-triggered skill menu) for hands-on testing.

Try it in dev-playground

pnpm --filter=dev-playground dev, open /agent (Helper agent):

  • Type / → a menu of the agent's skills (/haiku); ↑/↓ + Enter/Tab to insert.
  • /haiku what's the weather in Paris? forces the skill; "give me a haiku about NYC taxi trips" triggers auto-load (watch the load_skill tool call).

Tests & verification

New coverage across skills.test.ts, dispatch-tool-call, skill-volume, skill-client, and the use-agent-chat hook. Full appkit (3075) and appkit-ui (366) suites pass; all packages typecheck; docs build succeeds.

Deferred to v2 (non-goals here)

Script/code execution from skills; allowed-tools enforcement (advisory only in v1); per-user (OBO) skill volumes; TTL refresh of volume listings; marketplace / end-user-uploaded skills; standalone runAgent skill parity.

Add the skill model, SKILL.md parser, filesystem loader, and per-agent
catalog resolution (visibility opt-in + cross-source collision handling)
for runtime Agent Skills. Wire a `skills:` frontmatter list and an
`autoInheritSkills` config knob into the agents plugin; each registered
agent now carries a resolved skill catalog. No prompt/tool wiring yet.

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Inject each agent's skill name+description into its system prompt (after
composition, so it survives custom base prompts) and add two read-only
built-in tools: load_skill returns a skill's body plus a manifest of
bundled files, and read_skill_file reads a listed bundle resource through
a directory-containment guard. Bundle sources end-to-end; catalog volumes
follow. Deferred: script execution, allowed-tools enforcement.

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Discover catalog skills from a configured UC Volume (skillsVolume config or
DATABRICKS_VOLUME_AGENT_SKILLS) at boot and on reload, read as the service
principal via FilesConnector, merged into the shared pool alongside bundle
skills. read_skill_file now serves volume resources too. Adds an optional
volume resource to the manifest and a skillCredentialMode seam (sp default;
obo reserved for v2).

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Ship each agent's skill catalog in clientConfig() so the client can offer a
/skill-name picker; accept an optional skill on the chat request and eagerly
inject that skill's instructions into the turn (deterministic force-load,
load_skill still available for auto-select). useAgentChat.send gains a
{ skill } option and parses a leading /skill-name token; the template
AgentChat page renders a skill dropdown.

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Add a Skills section to the agents plugin docs (layout, opt-in visibility,
load_skill/read_skill_file, /skill-name, catalog volume, and v1 caveats:
scripts not run, allowed-tools advisory, SP-read). Confirm sub-agents get
skills uniformly via buildRegisteredAgent (tests). Ship a tracer-bullets
example skill under the template and opt the planner agent into it. Includes
regenerated API reference for the new skill types.

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Ships a global `haiku` skill (config/agents/skills/haiku, with a bundled
reference.md) and opts the default `helper` agent into it, and teaches the
agent chat box to parse a leading /skill-name token into the chat request's
skill field. Lets you watch auto-load (ask for a haiku) and deterministic
force-load (/haiku ...) end to end.

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Regenerated appkit.plugins.json to include the optional agents-skills volume
resource added to the agents plugin manifest.

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Typing `/` in the agent chat box now opens a filtered menu of the active
agent's skills (from clientConfig), with arrow-key navigation and
Enter/Tab/click to insert `/skill-name `. Reads the per-agent catalog the
agents plugin exposes in its boot config.

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Biome formatting for the merged mlflowRunId + skill destructure (rebase
doesn't run the pre-commit formatter).

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

📦 Bundle size report

Compared against bundle-size-baseline.json (main).

@databricks/appkit

npm tarball (packed): 862 KB (+22 KB) — gzipped download (dist + bin; excludes release-only docs/NOTICE).

dist raw gzip
JS (runtime) 893 KB (+24 KB) 312 KB (+8.9 KB)
Type declarations 321 KB (+6.4 KB) 111 KB (+2.5 KB)
Source maps 1.7 MB (+42 KB) 581 KB (+15 KB)
Other 11 KB 3.7 KB
Total 2.9 MB (+72 KB) 1008 KB (+26 KB)
Per-entry composition (own code — deps external (as shipped))
Entry Initial (gz) Lazy (gz) Total (gz) node_modules (min) Own code (min)
. 88 KB 2.5 KB 91 KB external 288 KB
./beta 54 KB (+5.6 KB) 458 B 55 KB (+5.6 KB) external 159 KB (+16 KB)
./type-generator 21 KB 0 B 21 KB external 60 KB

Chunks:

Entry Chunk Load Size (gz)
. index.js initial 84 KB
. utils.js initial 4.0 KB
. remote-tunnel-manager.js lazy 2.5 KB
./beta beta.js initial 38 KB
./beta stream-manager.js initial 5.8 KB
./beta wide-event-emitter.js initial 3.2 KB
./beta databricks.js initial 3.0 KB
./beta configuration.js initial 2.1 KB
./beta service-context.js initial 1.3 KB
./beta client.js initial 431 B
./beta client-options.js initial 219 B
./beta supervisor-api.js lazy 194 B
./beta databricks.js lazy 142 B
./beta index.js lazy 122 B
./type-generator index.js initial 21 KB

@databricks/appkit-ui

npm tarball (packed): 343 KB (+758 B) — gzipped download (dist + bin; excludes release-only docs/NOTICE).

dist raw gzip
JS (runtime) 390 KB (+316 B) 131 KB (+158 B)
Type declarations 228 KB (+300 B) 83 KB (+130 B)
Source maps 754 KB (+1.2 KB) 248 KB (+493 B)
CSS 16 KB 3.3 KB
Total 1.4 MB (+1.8 KB) 465 KB (+781 B)
Per-entry composition (consumer bundle — deps bundled, peerDeps external)
Entry Initial (gz) Lazy (gz) Total (gz) node_modules (min) Own code (min)
./js 5.3 KB 49 KB 55 KB 208 KB 14 KB
./js/beta 20 B 0 B 20 B 0 B 0 B
./react 432 KB (+117 B) 49 KB 480 KB (+117 B) 1.3 MB 175 KB (+168 B)
./react/beta 1.0 KB 0 B 1.0 KB 0 B 1.9 KB

Chunks:

Entry Chunk Load Size (gz)
./js index.js initial 5.2 KB
./js chunk initial 120 B
./js apache-arrow lazy 49 KB
./js/beta beta.js initial 20 B
./react index.js initial 430 KB
./react tslib initial 2.1 KB
./react apache-arrow lazy 49 KB
./react/beta beta.js initial 1.0 KB

@github-actions

Copy link
Copy Markdown
Contributor

🤖 AppKit PR bot

🔬 Run evals

Start an eval for this PR from the evals-monitor app: Go to Evals Monitor →

📦 Try this PR's app template

Scaffolds a new app from this PR's SDK build. Run it in any folder (requires the GitHub CLI — gh auth login — and the Databricks CLI):

gh run download 31706710060 -R databricks/appkit -n appkit-template-0.60.0-pr.eb773ab-feat-agent-skills-532 -D appkit-pr-532 \
  && unzip -o "appkit-pr-532/appkit-template-0.60.0-pr.eb773ab-feat-agent-skills-532.zip" -d "appkit-pr-532" \
  && databricks apps init --template "appkit-pr-532"

The template pins @databricks/appkit and @databricks/appkit-ui to tarballs built from this branch, so the scaffolded app runs against this PR's code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant