feat(appkit): auto-discover code agents from server/agents/ - #533
Draft
MarioCadenas wants to merge 5 commits into
Draft
feat(appkit): auto-discover code agents from server/agents/#533MarioCadenas wants to merge 5 commits into
MarioCadenas wants to merge 5 commits into
Conversation
MarioCadenas
force-pushed
the
agents-discovery-dx
branch
from
August 13, 2026 14:31
8c9faed to
d956f58
Compare
Contributor
📦 Bundle size reportCompared against
|
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 879 KB (+10 KB) | 307 KB (+3.9 KB) |
| Type declarations | 318 KB (+2.7 KB) | 110 KB (+937 B) |
| Source maps | 1.7 MB (+20 KB) | 573 KB (+7.0 KB) |
| Other | 11 KB | 3.7 KB |
| Total | 2.9 MB (+33 KB) | 993 KB (+12 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 |
50 KB (+1.7 KB) | 457 B | 51 KB (+1.7 KB) | external | 148 KB (+4.6 KB) |
./type-generator |
21 KB | 0 B | 21 KB | external | 61 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 | 34 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 | 434 B |
./beta |
client-options.js |
initial | 220 B |
./beta |
supervisor-api.js |
lazy | 192 B |
./beta |
databricks.js |
lazy | 142 B |
./beta |
index.js |
lazy | 123 B |
./type-generator |
index.js |
initial | 21 KB |
@databricks/appkit-ui
npm tarball (packed): 342 KB — gzipped download (dist + bin; excludes release-only docs/NOTICE).
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 390 KB | 130 KB |
| Type declarations | 228 KB | 83 KB |
| Source maps | 753 KB | 248 KB |
| CSS | 16 KB | 3.3 KB |
| Total | 1.4 MB | 465 KB |
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 | 49 KB | 480 KB | 1.3 MB | 175 KB |
./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 |
Contributor
🤖 AppKit PR bot🔬 Run evalsStart an eval for this PR from the evals-monitor app: Go to Evals Monitor → 📦 Try this PR's app templateScaffolds a new app from this PR's SDK build. Run it in any folder (requires the GitHub CLI — gh run download 32042203358 -R databricks/appkit -n appkit-template-0.61.1-pr.4ec510a-agents-discovery-dx-533 -D appkit-pr-533 \
&& unzip -o "appkit-pr-533/appkit-template-0.61.1-pr.4ec510a-agents-discovery-dx-533.zip" -d "appkit-pr-533" \
&& databricks apps init --template "appkit-pr-533"The template pins |
Drop-in code agents: a file `server/agents/<id>.ts` that
`export default createAgent(...)` is discovered at startup — the agent id
is the filename, so there is no agent map and no import at the call site
(`agents()`). Symmetric with markdown agents in `config/agents/`.
Discovery is a runtime scan resolved by NODE_ENV: dev scans
`server/agents/*.ts` under tsx; a bundled server scans the compiled
`dist/agents` (or `build/agents`) `*.js`. `createAgent` brands its result
(`Symbol.for("appkit.agent")`) so the loader picks the agent out of a
module's exports and skips helpers and bundler chunks. The template's
tsdown config lists `server/agents/*.ts` as build entries so the compiled
files exist for the production scan (a runtime scan of a dynamic path
would be dropped by the bundler — the trap this avoids).
Backward compatible: `agents({ agents: { ... } })` still works and emits a
one-time deprecation warning; `createAgent({ name })` is still honored;
markdown discovery is unchanged.
Also migrates the dev-playground reference app to the new pattern.
Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
- Resolve the code-agents dir built-first and NODE_ENV-independently
(prefer dist/agents|build/agents .js; fall back to server/agents .ts
only when no built dir exists). Fixes a boot crash where a compiled
server run without NODE_ENV=production imported .ts under plain Node.
- Loader gracefully skips (warns) when it cannot import a module for lack
of a TS loader, instead of crashing setup.
- Drop the phantom `appkit generate-agents` command from the deprecation
JSDoc and the scaffold template — discovery is a runtime scan.
- Discovered id colliding with the deprecated agents({ agents }) map now
warns and lets discovery win, rather than throwing at boot on upgrade.
- Document that createAgent brands (mutates) its input; de-noise the
prod zero-agents warning when the deprecated map is in use; template
tsdown clean:true so a deleted agent can't linger in dist/agents.
- Extract resolveCodeAgentsDir as a pure function and unit-test the
built-first ordering, override, and fallback; add map-only and
defaultAgent-not-registered regression tests.
Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
- Derive the first-registered default from the agent Map instead of tracking a separate variable + param. - Collapse the isIgnored test/spec cross-product to one regex; derive the agent id via path.parse (drops a duplicated extension list). - Reuse the loader's isIgnored in hasCodeAgentSources so the "sources exist but nothing discovered" warning no longer fires for index/test-only dirs. - Trim verbose docblocks/comments to their load-bearing facts and keep the brand rationale in one place. Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Every agent is a folder under server/agents/<id>/ holding agent.md
(markdown) or agent.ts (code); the folder name is the id.
- Code loader scans <id>/agent.{ts,tsx,js,mjs}, built-first (dist/build
over source); folders without an entry file are skipped.
- Markdown loader skips folders lacking agent.md (was a throw) so code
folders and asset dirs coexist; drop the RESERVED_DIRS list.
- One dir knob (default server/agents) feeds both loaders; retire
codeAgentsDir. config/agents is read as a deprecated fallback
(per-agent merge, new location wins, one-time warning).
- Cross-kind sub-agent references resolve by folder id.
- Migrate template, dev-playground, docs, and test fixtures.
Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
MarioCadenas
force-pushed
the
agents-discovery-dx
branch
from
August 17, 2026 13:23
c9b7e58 to
b44b5bd
Compare
- resolveCodeAgentsDir: a relative `dir` is now built-first (dist/<name>, build/<name> probed before source); only an absolute path is verbatim. Fixes prod discovering zero code agents when `dir` was a relative path (e.g. the documented default typed explicitly) — dev worked, prod empty. - Cross-location sub-agent refs resolve mid-migration: config/agents loads first and its defs feed the server/agents resolution. - hasCodeAgentSources + its warning track the configured dir; drop the duplicate DEFAULT_AGENTS_DIR constant. - Discover symlinked agent folders in both loaders. - Template AgentChat.tsx: correct the scaffold's shown agent paths. - Docs: dir:false also disables the config/agents fallback; note stale-build shadowing in dev; fix AgentDefinition.name tsdoc. - Tests: cover the config/agents fallback (merge, precedence, one-time warning), cross-dir refs, dir:false, and built-first for a relative dir. Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Code agents are now auto-discovered from
server/agents/, symmetric with markdown agents inconfig/agents/. A file thatexport default createAgent(...)is discovered at startup — its id is the filename — so the plugin call collapses toagents()with no agent map and no import.How
NODE_ENV. Dev scansserver/agents/*.tsundertsx; a bundled server scans the compileddist/agents(orbuild/agents)*.js. TheNODE_ENVguard keeps a stale build dir from shadowing live sources in dev.createAgentstamps a non-enumerableSymbol.for("appkit.agent")on its result; the loader keeps branded exports and skips helpers / bundler chunks. One agent per file.tsdownconfig listsserver/agents/*.tsas build entries, so the compileddist/agents/*.jsexist for the scan. Static bundling was the alternative considered and rejected (import.meta.globcrashestsxin dev).Backward compatibility
agents({ agents: { ... } })still works and emits a one-time deprecation warning.createAgent({ name })is still honored.config/agents/) is unchanged — it stays a runtime data scan.Also in this PR
server/agents/*.ts; build emitsbuild/agents/*.mjs).Verification
pnpm -r typecheckclean ·pnpm check(biome) 0 errors · appkit + shared 3388 tests pass ·pnpm build+pnpm docs:buildsucceed.npm run dev(tsx,.ts) and a bundlednode dist/agents/*.jsrun.tscerror count unchanged (2046 → 2046 — pre-existingclient/*.tsxnoise, none in the new files); its server builds and prod-discovers all four agents.Not verified here
Open follow-ups
server/agents/(breaking; deferred — theconfig/agents/convention was kept to avoid breaking existing apps).Draft — opening for early review.