Saltar al contenido principal
Versión: Next (sin publicar)

Las propias del kit, y las de tu agente

Las extensiones internas son código: las cuatro del kit, creadas por sus factorías, y las que tu agente escriba como un objeto. Ambas son Extensions, listadas en el spec.

Activar las del kit​

import { awareness, knowledge, memory, sources, type AgentSpec } from "@falkenslab/agent-kit";

const spec: AgentSpec<Config> = {
// …
extensions: [
sources({ dir: (config) => path.join(config.projectDir, "sources") }),
knowledge({ dir: (config) => path.join(config.projectDir, "knowledge") }),
memory({ dir: path.join(os.homedir(), ".my-agent", "memory") }),
diceExtension,
],
};
  • Las del kit se crean con sus factorías, cada una con sus propias opciones; la propia de un agente es un objeto (consulta más abajo).
  • Una opción de carpeta (dir, un FolderOption) es una ruta, o una función de la configuración de la sesión que devuelve una (o undefined): el spec es estático, mientras que las carpetas suelen depender del proyecto. Las factorías son genéricas sobre el tipo de configuración: knowledge<Config>({ dir: (config) => config.courseDir }).
  • Ninguna está activa por defecto, y solo la lista del spec activa una: una carpeta pertenece a la extensión que la nombra.
  • Una extensión a la que a la sesión le falta algo (su carpeta: "needs a folder (dir)") se queda fuera, igual que una cuyas capacidades requeridas no proporciona nada activado (consulta Capacidades). El prompt del sistema dice cuáles están desactivadas y por qué, para que el agente pueda contárselo a la persona.
ExtensiónOpcionesQué aporta
awarenessawareness({ guide? }): guide, la ruta absoluta de una guía en markdown del dominio del agente. Necesita identity en el spec.Awareness: la sección del prompt "Who you are", about_me (lo que el agente es ahora mismo, leído de la sesión en cada llamada, y su guide) y la skill help (cómo se usa el chat del kit). Proporciona self-awareness.
sourcessources({ dir, saveDescription? }): dir, la carpeta de los originales; saveDescription, la descripción de la herramienta save_to_sources en palabras del agente.Los originales: las herramientas de fuentes (list_sources, extract_text, save_to_sources, download_to_sources, y request_file, retire_source fuera del modo autónomo), Read/Glob/Grep sobre la carpeta, sin escribir nunca en ella, y su sección del prompt. Consulta Fuentes. Proporciona sources.
knowledgeknowledge({ dir, pageTypes?, store? }): dir, la carpeta de la base de conocimiento; pageTypes, tus propios tipos de página; store(config, dir), otro almacén.La base de conocimiento: las herramientas knowledge_* sobre un almacén, su sección del prompt con las preferencias de la persona, sus skills y comandos; las herramientas de ficheros nunca llegan a la carpeta. Proporciona knowledge-base.
memorymemory({ dir }): dir, una carpeta propia del agente fuera de cualquier proyecto.La memoria de la persona, a través de todos sus proyectos: sus herramientas (recall, remember, forget), su sección del prompt con lo que recuerda, /memory:list y /memory:forget; solo se guarda a partir de lo que escribió la persona. Proporciona person-memory.

Cada una es dueña de sus datos y nunca llama a las demás: el modelo las conecta a través de sus herramientas (consulta Base de conocimiento y fuentes).

Escribir una en el código de tu agente​

Una extensión que solo necesita un agente, o que necesita las piezas internas del kit (un panel, un almacén pasado desde código, sus propias carpetas para las herramientas de ficheros, hooks), es código en el agente: una carpeta de plugin en su proyecto más un objeto que implementa Extension. Una que podría usar cualquier agente es mejor que sea instalable.

import path from "node:path";
import { createSdkMcpServer, tool, type Extension } from "@falkenslab/agent-kit";
import { z } from "zod";

export const diceExtension: Extension = {
name: "dice", // the same as its plugin's
plugin: path.join(__dirname, "extensions", "dice"), // .claude-plugin/plugin.json, skills…
// missing: ({ config }) => (config.diceDir ? undefined : "needs `diceDir` in the config"),
async contribute({ config, spec, runDir, mode, interactive }) {
const roll = tool("roll", "Rolls a die.", { sides: z.number() }, async ({ sides }) => ({
content: [{ type: "text" as const, text: String(1 + Math.floor(Math.random() * sides)) }],
}), { annotations: { readOnlyHint: true } });
return {
mcpServers: { dice: createSdkMcpServer({ name: "dice", version: "1.0.0", tools: [roll] }) },
promptSection: "## Dice\nWhen the person wants a roll, `roll` it: never make one up.",
readOnlyTools: ["mcp__dice__roll"], // plan mode lets it through
toolLabels: { mcp__dice__roll: { label: (input) => `Rolling a ${String(input.sides)}-sided die`, phrase: ["rolled once", "rolled {n} times"] } },
helpLines: ["Dice: `roll` rolls one."],
};
},
};

Lo que puede llevar una contribución (todas las partes son opcionales):

CampoQué hace
mcpServersSus servidores MCP, por nombre: sus herramientas son mcp__<name>__<tool>.
promptSectionUna sección del prompt del sistema, después de la lista de Extensions. Mantenla corta: para qué sirve y sus reglas. Los procedimientos van en skills.
fileToolsHerramientas de ficheros integradas que la sesión debe tener (Read, Glob, Grep…).
readOnlyDirsCarpetas que las herramientas de ficheros pueden leer y buscar, nunca escribir.
toolOnlyDirsCarpetas a las que solo se llega con sus propias herramientas, nunca con las de ficheros, con qué usar en su lugar (la denegación lo dice).
readOnlyToolsSus herramientas que solo leen: el modo plan las deja pasar; cualquier otra herramienta MCP se deniega ahí.
readOnlyHintServersSus servidores MCP cuyas herramientas deja pasar el modo plan cuando el servidor las marca con readOnlyHint: true, consultado mientras la sesión se ejecuta. Una extensión instalada sin readOnlyTools en su manifiesto lo establece; una en tu código suele listar readOnlyTools en su lugar.
selfAskingToolsSus herramientas que preguntan ellas mismas a la persona (un panel): el modo interactivo no pregunta antes de usarlas.
toolLabelsCómo muestra el chat sus herramientas, por nombre completo: la línea de cada una y cómo cuenta en un resumen plegado, en el idioma del kit. Consulta Las etiquetas de una extensión.
hooksSus hooks del SDK, por evento, que se ejecutan después de los propios del kit (la memoria escucha los mensajes de la persona con UserPromptSubmit).
helpLinesLo que dice de sí misma en esta sesión (sus comandos, su carpeta), que el about_me de la extensión awareness le da al agente.
apiLo que la extensión entrega al host: buildSessionOptions() devuelve el de cada extensión activa en apis, por nombre, y el api(name) del controlador del chat lo da (el addSource de la extensión sources en apis.sources.addSource, el almacén de la base de conocimiento en apis.knowledge.knowledgeStore).

missing(context) dice por qué la extensión no puede ejecutarse en esta sesión (una carpeta que necesita), o undefined. El contexto tiene la configuración, el spec, la carpeta de la ejecución, el modo, si se le puede preguntar a una persona, y capabilities: lo que proporcionan las extensiones activas de la sesión (los provides de sus manifiestos), para una extensión que funciona de otra forma junto a otra. Se conoce una vez resueltas las extensiones, así que está vacío en missing() y lleno en contribute(): la base de conocimiento explica cómo relacionar sus resúmenes con los originales cuando capabilities.has("sources").

Su plugin se carga como cualquiera de los del agente, así que sus skills, comandos y subagentes llevan su nombre (dice:…); con skills: "plugins" sus skills se ofrecen sin nombrarlas, y sus subagentes (agents/*.md) se registran como los propios del agente (consulta Subagentes en un plugin). Su manifiesto lleva sus capacidades en metadata["agent-kit"] (provides, requires), igual que el de una instalada (Referencia del manifiesto).