feat(appkit): add agents() plugin, createAgent() factory, and .toolkit()#294
Closed
MarioCadenas wants to merge 1 commit intoagent/5a-plugin-base-refactorfrom
Closed
feat(appkit): add agents() plugin, createAgent() factory, and .toolkit()#294MarioCadenas wants to merge 1 commit intoagent/5a-plugin-base-refactorfrom
MarioCadenas wants to merge 1 commit intoagent/5a-plugin-base-refactorfrom
Conversation
Introduce a redesigned agent API while keeping the previous shape exported
for migration. The new API separates agent *definition* (pure data) from
app *composition* (plugin registration).
New public surface:
- createAgent(def): pure factory that returns an AgentDefinition after
DFS cycle-detecting the sub-agent graph. No side effects; safe at module
top-level.
- agents(config): plugin factory (plural) for createApp. Loads markdown
agents from ./config/agents by default, merges code-defined agents,
resolves toolkit refs + ambient tools, builds per-agent tool indexes,
and mounts /invocations. Internally registers under plugin name "agent"
(singular) so its routes mount at /api/agent/* — matches the existing
URL convention and keeps the public factory export as agents() for DX.
- runAgent(def, input): standalone executor for code-only agents without
createApp. Throws a clear error if invoked against a ToolkitEntry
(plugin tools require PluginContext).
- loadAgentFromFile, loadAgentsFromDir: public loaders. Use js-yaml for
frontmatter (replaces the hand-rolled regex parser).
- tool() + mcpServer() unchanged; tools are now a keyed record on
AgentDefinition.tools with keys = LLM-visible tool-call names.
.toolkit() on every ToolProvider plugin:
- analytics(), files(), genie(), lakebase() each expose a toolkit(opts)
method on their PluginData. Users spread it into AgentDefinition.tools.
- buildToolkitEntries() util produces branded ToolkitEntry records with
{ prefix, only, except, rename } filtering. Dispatches through
PluginContext.executeTool for OBO + telemetry.
- toPluginWithInstance() variant of toPlugin() eagerly constructs the
plugin instance at factory-call time. AppKit._createApp reuses the
instance instead of re-constructing.
Asymmetric auto-inherit default: markdown agents without explicit
toolkits get every registered plugin's tools by default (file: true).
Code-defined agents start empty (code: false). Configurable via
autoInheritTools: { file, code } with boolean shorthand.
Frontmatter schema (array-of-string-or-object):
toolkits:
- analytics
- files: [uploads.list, uploads.read]
- genie: { except: [getConversation] }
tools: [get_weather]
endpoint: databricks-claude-sonnet-4-5
default: true
Load-time errors throw with a clear "Available: ..." listing. No silent
skip.
Sub-agents: parent emits tool_call to agent-<key>; AgentsPlugin runs the
child's adapter with no shared thread state. Cycles rejected at load.
Deprecations (kept exported, JSDoc @deprecated only, no runtime warnings):
- agent() plugin -> use agents() (plural).
- createAgent(config) app shortcut -> re-exported as createAgentApp().
The name createAgent is now the pure factory.
Tests: 37 new tests covering create-agent cycles, build-toolkit filters,
load-agents (js-yaml, missing refs, toolkit resolution), run-agent
standalone, and AgentsPlugin (auto-inherit asymmetry, sub-agent
dispatch, code-over-markdown precedence). All 1301 tests pass.
Adds js-yaml (+ @types/js-yaml) as a runtime dep (~20 KB gzipped).
Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
This was referenced Apr 21, 2026
Collaborator
Author
|
Superseded by the v2 6-PR stack:
The v2 stack reorganizes the same work so no PR ships API that a later PR deletes. Start at #301 for the new entry point. Branches from this older stack are preserved unchanged. |
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.
Summary
Introduces the new agents system — pure-data
AgentDefinitions, markdown-driven agent discovery, and theagents()plugin that registers them withcreateApp. Replaces the oldagent()plugin +createAgentapp-shortcut (PR #286) with three focused primitives:createAgent(def)— pure factory atpackages/appkit/src/core/create-agent-def.ts. Returns the passed-in definition after cycle-detecting the sub-agent graph. No adapter construction, no side effects — safe at module top-level.agents(config)plugin — registers markdown agents fromconfig/agents/*.md(viajs-yaml) and merges code-defined agents. Builds per-agenttoolIndexmaps. Mounts/invocations+/chatroutes. Exposesappkit.agent.*runtime helpers (register,list,get,reload,getThreads)..toolkit(opts?)method on coreToolProviderplugins (analytics/files/genie/lakebase) — returns a keyed record ofToolkitEntrymarkers, suitable for spreading intoAgentDefinition.tools.Key behaviors
endpoint,default,toolkits,tools,maxSteps,maxTokens,baseSystemPrompt. Unknown keys logged and ignored.ToolProvider's tools (file: true); code-defined agents default to strict (code: false). Rationale: prompt authors want zero ceremony; engineers want explicit dependencies. Configurable viaautoInheritTools: { file: boolean, code: boolean }.agents: { child }inside an AgentDefinition exposesagent-<key>tools on the parent. Cycle-detected at build time.runAgent(def, input)standalone executor for tests / CLI scripts — drives the adapter outside ofcreateAppwith inline tools.New public exports
agents,createAgent(new pure-data meaning),runAgent,isToolkitEntry,loadAgentFromFile,loadAgentsFromDir, plus typesAgentDefinition,AgentsPluginConfig,AgentTool,ToolkitEntry,ToolkitOptions,PromptContext,BaseSystemPromptOption.Dependencies
js-yamlruntime dep for frontmatter parsing.PR Stack
agents()plugin +createAgent(def)+.toolkit()(this PR)agents()— feat(appkit): migrate agent-app and docs to the new agents() plugin #295preparePluginsforwards eager instance — refactor(appkit): forward eager plugin instance through preparePlugins #297fromPlugin()API — feat(appkit): add fromPlugin() for referencing plugin tools in code-defined agents #298agent()+createAgentApp— chore(appkit): remove deprecated agent() plugin and createAgentApp shortcut #299toPluginWithInstance+ bug fixes — refactor(appkit): retire toPluginWithInstance; consolidate on fromPlugin + fix schema/routing bugs #300Test plan
packages/appkit/src/plugins/agents/tests/covering markdown loading, code-agent registration, auto-inherit asymmetry, sub-agent tool synthesis, cycle detection,.toolkit()entry shape