Skip to content

feat(appkit): add agents() plugin, createAgent() factory, and .toolkit()#294

Closed
MarioCadenas wants to merge 1 commit intoagent/5a-plugin-base-refactorfrom
agent/5b-agents-plugin
Closed

feat(appkit): add agents() plugin, createAgent() factory, and .toolkit()#294
MarioCadenas wants to merge 1 commit intoagent/5a-plugin-base-refactorfrom
agent/5b-agents-plugin

Conversation

@MarioCadenas
Copy link
Copy Markdown
Collaborator

@MarioCadenas MarioCadenas commented Apr 21, 2026

Summary

Introduces the new agents system — pure-data AgentDefinitions, markdown-driven agent discovery, and the agents() plugin that registers them with createApp. Replaces the old agent() plugin + createAgent app-shortcut (PR #286) with three focused primitives:

  • createAgent(def) — pure factory at packages/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 from config/agents/*.md (via js-yaml) and merges code-defined agents. Builds per-agent toolIndex maps. Mounts /invocations + /chat routes. Exposes appkit.agent.* runtime helpers (register, list, get, reload, getThreads).
  • .toolkit(opts?) method on core ToolProvider plugins (analytics/files/genie/lakebase) — returns a keyed record of ToolkitEntry markers, suitable for spreading into AgentDefinition.tools.

Key behaviors

  • Markdown frontmatter (real YAML, not regex-based): endpoint, default, toolkits, tools, maxSteps, maxTokens, baseSystemPrompt. Unknown keys logged and ignored.
  • Asymmetric auto-inherit: markdown agents default to inheriting every registered ToolProvider's tools (file: true); code-defined agents default to strict (code: false). Rationale: prompt authors want zero ceremony; engineers want explicit dependencies. Configurable via autoInheritTools: { file: boolean, code: boolean }.
  • Sub-agents: agents: { child } inside an AgentDefinition exposes agent-<key> tools on the parent. Cycle-detected at build time.
  • runAgent(def, input) standalone executor for tests / CLI scripts — drives the adapter outside of createApp with inline tools.

New public exports

agents, createAgent (new pure-data meaning), runAgent, isToolkitEntry, loadAgentFromFile, loadAgentsFromDir, plus types AgentDefinition, AgentsPluginConfig, AgentTool, ToolkitEntry, ToolkitOptions, PromptContext, BaseSystemPromptOption.

Dependencies

  • Adds js-yaml runtime dep for frontmatter parsing.

PR Stack

  1. Shared types + Adapters — feat(appkit): add shared agent types and LLM adapter implementations #282
  2. Tool types + MCP client — feat(appkit): add FunctionTool, HostedTool types and MCP client #283
  3. Agent plugin core + ToolProvider implementations — feat(appkit): add agent plugin core and ToolProvider implementations #284
  4. PluginContext mediator — feat(appkit): add PluginContext mediator for inter-plugin communication #285
  5. createAgent + agent-app + docs (v1) — feat(appkit): add createAgent wrapper, agent-app, and API docs #286
  6. Plugin context-binding separation — refactor(appkit): separate plugin context binding from plugin construction #293
  7. agents() plugin + createAgent(def) + .toolkit() (this PR)
  8. agent-app + docs migrated to agents()feat(appkit): migrate agent-app and docs to the new agents() plugin #295
  9. Relocate shared agent utilities — refactor(appkit): relocate shared agent utilities into plugins/agents #296
  10. preparePlugins forwards eager instance — refactor(appkit): forward eager plugin instance through preparePlugins #297
  11. fromPlugin() API — feat(appkit): add fromPlugin() for referencing plugin tools in code-defined agents #298
  12. Retire deprecated agent() + createAgentAppchore(appkit): remove deprecated agent() plugin and createAgentApp shortcut #299
  13. Retire toPluginWithInstance + bug fixes — refactor(appkit): retire toPluginWithInstance; consolidate on fromPlugin + fix schema/routing bugs #300

Test plan

  • New test suite in packages/appkit/src/plugins/agents/tests/ covering markdown loading, code-agent registration, auto-inherit asymmetry, sub-agent tool synthesis, cycle detection, .toolkit() entry shape
  • Full vitest suite passing
  • Typecheck clean

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>
@MarioCadenas
Copy link
Copy Markdown
Collaborator Author

Superseded by the v2 6-PR stack:

  1. Shared agent types + LLM adapters — feat(appkit): shared agent types and LLM adapter implementations #301
  2. Tool primitives + ToolProvider surfaces — feat(appkit): tool primitives and ToolProvider surfaces on core plugins #302
  3. Plugin infrastructure (attachContext + PluginContext) — feat(appkit): plugin infrastructure — attachContext + PluginContext mediator #303
  4. agents() plugin + createAgent(def) + markdown-driven agents — feat(appkit): agents() plugin, createAgent(def), and markdown-driven agents #304
  5. fromPlugin() DX + runAgent plugins arg + toolkit-resolver — feat(appkit): fromPlugin() DX, runAgent plugins arg, shared toolkit-resolver #305
  6. Reference app + dev-playground + docs — feat(appkit): reference agent-app, dev-playground chat UI, docs, and template #306

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.

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