kraken-ai 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,6 +50,40 @@ if (result.status === "complete") {
50
50
  }
51
51
  ```
52
52
 
53
+ ## Adding skills to a kernel
54
+
55
+ `defineSkillTool` and `skillDiscoveryMessage` give you the [Agent Skills](https://agentskills.io/specification) progressive-disclosure pattern with no framework lock-in. The SDK stays governance-agnostic — you wire the loader to whatever backend fetches the skill body (an in-memory map for tests, a file walker for a CLI, an authenticated service for production).
56
+
57
+ ```ts
58
+ import { Agent, defineSkillTool, skillDiscoveryMessage, openai } from "kraken-ai";
59
+
60
+ const SKILLS = {
61
+ "pdf-processing": "# PDF Processing\n\nUse pdfminer.six to extract …",
62
+ "csv-cleaning": "# CSV Cleaning\n\nNormalize headers via …",
63
+ };
64
+
65
+ const skillTools = Object.keys(SKILLS).map((id) =>
66
+ defineSkillTool({
67
+ skillId: id,
68
+ description: `Load the ${id} skill body`,
69
+ load: async (skillId) => SKILLS[skillId as keyof typeof SKILLS],
70
+ }),
71
+ );
72
+
73
+ const catalog = skillDiscoveryMessage([
74
+ { skillId: "pdf-processing", description: "Extract structured data from PDFs" },
75
+ { skillId: "csv-cleaning", description: "Normalize and dedupe CSVs" },
76
+ ]);
77
+
78
+ const agent = new Agent({
79
+ model: openai("gpt-4o"),
80
+ instructions: `You are a data assistant.\n\n${catalog}`,
81
+ tools: skillTools,
82
+ });
83
+ ```
84
+
85
+ Only the skill names + descriptions are in the system prompt at startup. The full skill body is loaded only when the model decides to call the matching `load_skill_*` tool.
86
+
53
87
  ## Documentation
54
88
 
55
89
  - [Models](docs/models.md) — providers, lazy resolution, custom providers
package/dist/index.cjs CHANGED
@@ -318,10 +318,12 @@ __export(index_exports, {
318
318
  ValidationError: () => ValidationError,
319
319
  configure: () => configure,
320
320
  defineKernel: () => defineKernel,
321
+ defineSkillTool: () => defineSkillTool,
321
322
  formatEvent: () => formatEvent,
322
323
  google: () => google,
323
324
  mock: () => mock,
324
325
  openai: () => openai,
326
+ skillDiscoveryMessage: () => skillDiscoveryMessage,
325
327
  tool: () => tool
326
328
  });
327
329
  module.exports = __toCommonJS(index_exports);
@@ -388,17 +390,12 @@ var z = __toESM(require("zod"), 1);
388
390
  var delegationSchema = z.object({
389
391
  task: z.string().describe("The task to delegate to this team member")
390
392
  });
391
- var createDelegationTools = (team, propagatedOptions, childRunIds) => team.map((member) => ({
393
+ var createDelegationTools = (team, propagatedOptions) => team.map((member) => ({
392
394
  name: `delegate_to_${member.name}`,
393
395
  description: member.description ?? `Delegate a task to ${member.name}`,
394
396
  execute: async (args) => {
395
397
  const { task } = delegationSchema.parse(args);
396
- const childRunId = childRunIds?.get(member.name)?.shift();
397
- const childOptions = {
398
- ...propagatedOptions,
399
- ...childRunId ? { runId: childRunId } : {}
400
- };
401
- const result = await member.run([{ role: "user", content: task }], childOptions);
398
+ const result = await member.run([{ role: "user", content: task }], propagatedOptions);
402
399
  if (result.status === "complete") return result.output;
403
400
  throw new Error(`Delegation to ${member.name} was interrupted`);
404
401
  },
@@ -710,18 +707,11 @@ var createRunner = (config2) => {
710
707
  for (const { tc } of approved) {
711
708
  if (tc.name.startsWith("delegate_to_")) {
712
709
  const targetName = tc.name.replace("delegate_to_", "");
713
- const childRunId = crypto.randomUUID();
714
710
  emitter.emit({
715
711
  type: "delegation",
716
- childRunId,
712
+ childRunId: crypto.randomUUID(),
717
713
  childAgentName: targetName
718
714
  });
719
- const queue = options?._childRunIds?.get(targetName);
720
- if (queue) {
721
- queue.push(childRunId);
722
- } else {
723
- options?._childRunIds?.set(targetName, [childRunId]);
724
- }
725
715
  }
726
716
  }
727
717
  }
@@ -909,7 +899,6 @@ var Agent = class {
909
899
  }
910
900
  const resolvedThinkingLevel = options?.thinkingLevel ?? this.config.thinkingLevel;
911
901
  const resolvedMaxOutputTokens = options?.maxOutputTokens ?? this.config.maxOutputTokens;
912
- const childRunIds = /* @__PURE__ */ new Map();
913
902
  if (this.config.team?.length) {
914
903
  const propagated = {
915
904
  middleware: options?.middleware,
@@ -920,7 +909,7 @@ var Agent = class {
920
909
  ...resolvedThinkingLevel ? { thinkingLevel: resolvedThinkingLevel } : {},
921
910
  ...resolvedMaxOutputTokens != null ? { maxOutputTokens: resolvedMaxOutputTokens } : {}
922
911
  };
923
- const delegationTools = createDelegationTools(this.config.team, propagated, childRunIds);
912
+ const delegationTools = createDelegationTools(this.config.team, propagated);
924
913
  allTools.push(...delegationTools);
925
914
  }
926
915
  const runner = createRunner({
@@ -937,7 +926,7 @@ var Agent = class {
937
926
  responseSchema: this.config.outputSchema ? z2.toJSONSchema(this.config.outputSchema, { target: "draft-2020-12" }) : void 0,
938
927
  logLevel: this.config.logLevel
939
928
  });
940
- const result = await runner.run(messages, { ...options, runId, _childRunIds: childRunIds });
929
+ const result = await runner.run(messages, { ...options, runId });
941
930
  if (result.status === "complete" && this.config.outputSchema) {
942
931
  const validated = await this.produceStructuredOutput(result, options);
943
932
  options?.onEvent?.({
@@ -1115,6 +1104,9 @@ var mock = (config2) => {
1115
1104
  // src/index.ts
1116
1105
  init_openai();
1117
1106
 
1107
+ // src/skills.ts
1108
+ var z4 = __toESM(require("zod"), 1);
1109
+
1118
1110
  // src/tool.ts
1119
1111
  var z3 = __toESM(require("zod"), 1);
1120
1112
  init_errors();
@@ -1155,6 +1147,43 @@ Hint: The LLM provided arguments that don't match the tool's parameter schema. T
1155
1147
  }
1156
1148
  };
1157
1149
  };
1150
+
1151
+ // src/skills.ts
1152
+ var skillContentBlock = (skillId, content) => `<skill_content name="${skillId}">
1153
+ ${content}
1154
+ </skill_content>`;
1155
+ var notLoadedMessage = (skillId) => `<skill_load_failed name="${skillId}">no content returned by loader</skill_load_failed>`;
1156
+ var defineSkillTool = (config2) => {
1157
+ const toolDescription = config2.description ?? (config2.displayName ? `Load the "${config2.displayName}" skill body.` : `Load the "${config2.skillId}" skill body.`);
1158
+ return tool({
1159
+ name: `load_skill_${config2.skillId.replace(/-/g, "_")}`,
1160
+ description: toolDescription,
1161
+ parameters: z4.object({
1162
+ args: z4.record(z4.string(), z4.unknown()).optional().describe("Optional arguments forwarded to the skill loader.")
1163
+ }),
1164
+ execute: async ({ args }) => {
1165
+ const content = await config2.load(config2.skillId, args);
1166
+ if (content === null || content === void 0) {
1167
+ return notLoadedMessage(config2.skillId);
1168
+ }
1169
+ return skillContentBlock(config2.skillId, content);
1170
+ }
1171
+ });
1172
+ };
1173
+ var skillDiscoveryMessage = (skills) => {
1174
+ if (skills.length === 0) return "";
1175
+ const blocks = skills.map((s) => {
1176
+ const name = s.displayName ?? s.skillId;
1177
+ return ` <skill id="${s.skillId}" name="${name}">${s.description}</skill>`;
1178
+ });
1179
+ return [
1180
+ "<available_skills>",
1181
+ ...blocks,
1182
+ "</available_skills>",
1183
+ "",
1184
+ "If a skill is relevant to the user's request, call its load tool to retrieve the full skill body before relying on it."
1185
+ ].join("\n");
1186
+ };
1158
1187
  // Annotate the CommonJS export names for ESM import in node:
1159
1188
  0 && (module.exports = {
1160
1189
  Agent,
@@ -1166,9 +1195,11 @@ Hint: The LLM provided arguments that don't match the tool's parameter schema. T
1166
1195
  ValidationError,
1167
1196
  configure,
1168
1197
  defineKernel,
1198
+ defineSkillTool,
1169
1199
  formatEvent,
1170
1200
  google,
1171
1201
  mock,
1172
1202
  openai,
1203
+ skillDiscoveryMessage,
1173
1204
  tool
1174
1205
  });
package/dist/index.d.cts CHANGED
@@ -389,8 +389,6 @@ interface RunOptions {
389
389
  responseSchema?: Record<string, unknown>;
390
390
  /** When true, tool calls are logged but not executed. */
391
391
  dryRun?: boolean;
392
- /** @internal Shared map for pre-generated child runIds during delegation. */
393
- _childRunIds?: Map<string, string[]>;
394
392
  }
395
393
  /** Specification for spawning a sub-agent from a kernel. */
396
394
  interface SpawnSpec {
@@ -646,6 +644,74 @@ declare const mock: (config?: MockModelConfig) => MockModel;
646
644
  */
647
645
  declare const openai: (_modelId: OpenAIModelId) => Model;
648
646
 
647
+ /**
648
+ * Configuration for {@link defineSkillTool}.
649
+ *
650
+ * @typeParam TLoadResult - Inferred return type of the `load` callback.
651
+ * Whatever the loader returns is wrapped in a `<skill_content>` block
652
+ * and returned to the LLM verbatim, so callers can shape the payload
653
+ * for their own progressive-disclosure tier.
654
+ */
655
+ interface SkillToolConfig {
656
+ /** Stable identifier for the skill — what the LLM passes back via the tool call. */
657
+ skillId: string;
658
+ /** Optional display name surfaced in the tool description. */
659
+ displayName?: string;
660
+ /** Short description rendered alongside the tool definition. */
661
+ description?: string;
662
+ /**
663
+ * Loader invoked when the LLM activates this skill. Receives the
664
+ * (already-validated) `skillId` and any opaque `args` the LLM passed.
665
+ * Returning a string sends it back as `<skill_content>` text; returning
666
+ * `null` / `undefined` short-circuits with a "not loaded" message.
667
+ */
668
+ load: (skillId: string, args?: Record<string, unknown>) => Promise<string | null | undefined>;
669
+ }
670
+ /**
671
+ * Build a `loadSkill`-style tool for an Agent that defers content fetch
672
+ * to a caller-provided `load` function. The engine stays governance-
673
+ * agnostic: production deployments wire `load` to call a governance
674
+ * gateway; tests can inline an in-memory loader; CLIs can read from disk.
675
+ *
676
+ * The returned tool accepts a single `args?: Record<string, unknown>`
677
+ * parameter — keep it permissive so end-user skills can describe their
678
+ * own argument shape inside the skill body without re-engineering this
679
+ * helper.
680
+ *
681
+ * @example
682
+ * ```ts
683
+ * const skillTool = defineSkillTool({
684
+ * skillId: "pdf-processing",
685
+ * description: "Loads the PDF processing skill body",
686
+ * load: async (id, args) => `# Skill body for ${id}: ${JSON.stringify(args)}`,
687
+ * });
688
+ * ```
689
+ */
690
+ declare const defineSkillTool: (config: SkillToolConfig) => Tool;
691
+ /**
692
+ * Catalog entry for {@link skillDiscoveryMessage}. Mirrors the Agent
693
+ * Skills spec's tier-1 metadata shape (~100 tokens per skill) — `name`
694
+ * + `description` only.
695
+ */
696
+ interface SkillCatalogEntry {
697
+ skillId: string;
698
+ description: string;
699
+ /** Optional display name; defaults to `skillId` when absent. */
700
+ displayName?: string;
701
+ }
702
+ /**
703
+ * Build a system-reminder string listing every available skill so the
704
+ * LLM can discover what's loadable before deciding to call `loadSkill`.
705
+ *
706
+ * Format follows the Agent Skills spec's recommended catalog wrapping —
707
+ * `<available_skills>` with one `<skill>` block per entry plus an
708
+ * instruction footer telling the model when to call the loader.
709
+ *
710
+ * Returns an empty string when `skills` is empty, so callers can drop
711
+ * the result into their system prompt unconditionally.
712
+ */
713
+ declare const skillDiscoveryMessage: (skills: ReadonlyArray<SkillCatalogEntry>) => string;
714
+
649
715
  /**
650
716
  * Configuration for creating a tool.
651
717
  *
@@ -696,4 +762,4 @@ interface ToolConfig<TParams extends z.ZodType, TReturn = unknown> {
696
762
  */
697
763
  declare const tool: <TParams extends z.ZodType, TReturn>(config: ToolConfig<TParams, TReturn>) => Tool;
698
764
 
699
- export { Agent, type AgentConfig, type AgentConfigEvent, type AgentDelegationEvent, type AgentErrorEvent, type AgentEvent, type AgentEventBase, type AgentEventPayload, type AgentEventType, type AgentInterruptEvent, type AgentKillEvent, type AgentLLMCallEvent, type AgentLifecycleEvent, type AgentLike, type AgentNotificationEvent, type AgentRef, type AgentState, type AgentStructuredOutputCompleteEvent, type AgentThoughtEvent, type AgentToolCallEvent, type AgentTranscriptInitEvent, type ExecutionContext, type GenerateParams, type GenerateResponse, type GlobalConfig, type GoogleModelConfig, type GoogleModelId, type HumanDecision, type Interrupt, type Kernel, type KernelSignal, KrakenError, type LogLevel, type Message, type Middleware, type MiddlewareContext, type Model, type ModelParams, type ModelString, type OpenAIModelId, OutputValidationError, ProviderError, type RetryConfig, type RunOptions, type RunResult, type RunnerResponse, type SpawnSpec, type StreamChunk, type TeamAccessor, type ThinkingLevel, type Tool, type ToolCall, type ToolConfig, type ToolDefinition, ToolError, ToolInputValidationError, type ToolResult, type TransitionRecord, type Usage, ValidationError, configure, defineKernel, formatEvent, google, mock, openai, tool };
765
+ export { Agent, type AgentConfig, type AgentConfigEvent, type AgentDelegationEvent, type AgentErrorEvent, type AgentEvent, type AgentEventBase, type AgentEventPayload, type AgentEventType, type AgentInterruptEvent, type AgentKillEvent, type AgentLLMCallEvent, type AgentLifecycleEvent, type AgentLike, type AgentNotificationEvent, type AgentRef, type AgentState, type AgentStructuredOutputCompleteEvent, type AgentThoughtEvent, type AgentToolCallEvent, type AgentTranscriptInitEvent, type ExecutionContext, type GenerateParams, type GenerateResponse, type GlobalConfig, type GoogleModelConfig, type GoogleModelId, type HumanDecision, type Interrupt, type Kernel, type KernelSignal, KrakenError, type LogLevel, type Message, type Middleware, type MiddlewareContext, type Model, type ModelParams, type ModelString, type OpenAIModelId, OutputValidationError, ProviderError, type RetryConfig, type RunOptions, type RunResult, type RunnerResponse, type SkillCatalogEntry, type SkillToolConfig, type SpawnSpec, type StreamChunk, type TeamAccessor, type ThinkingLevel, type Tool, type ToolCall, type ToolConfig, type ToolDefinition, ToolError, ToolInputValidationError, type ToolResult, type TransitionRecord, type Usage, ValidationError, configure, defineKernel, defineSkillTool, formatEvent, google, mock, openai, skillDiscoveryMessage, tool };
package/dist/index.d.ts CHANGED
@@ -389,8 +389,6 @@ interface RunOptions {
389
389
  responseSchema?: Record<string, unknown>;
390
390
  /** When true, tool calls are logged but not executed. */
391
391
  dryRun?: boolean;
392
- /** @internal Shared map for pre-generated child runIds during delegation. */
393
- _childRunIds?: Map<string, string[]>;
394
392
  }
395
393
  /** Specification for spawning a sub-agent from a kernel. */
396
394
  interface SpawnSpec {
@@ -646,6 +644,74 @@ declare const mock: (config?: MockModelConfig) => MockModel;
646
644
  */
647
645
  declare const openai: (_modelId: OpenAIModelId) => Model;
648
646
 
647
+ /**
648
+ * Configuration for {@link defineSkillTool}.
649
+ *
650
+ * @typeParam TLoadResult - Inferred return type of the `load` callback.
651
+ * Whatever the loader returns is wrapped in a `<skill_content>` block
652
+ * and returned to the LLM verbatim, so callers can shape the payload
653
+ * for their own progressive-disclosure tier.
654
+ */
655
+ interface SkillToolConfig {
656
+ /** Stable identifier for the skill — what the LLM passes back via the tool call. */
657
+ skillId: string;
658
+ /** Optional display name surfaced in the tool description. */
659
+ displayName?: string;
660
+ /** Short description rendered alongside the tool definition. */
661
+ description?: string;
662
+ /**
663
+ * Loader invoked when the LLM activates this skill. Receives the
664
+ * (already-validated) `skillId` and any opaque `args` the LLM passed.
665
+ * Returning a string sends it back as `<skill_content>` text; returning
666
+ * `null` / `undefined` short-circuits with a "not loaded" message.
667
+ */
668
+ load: (skillId: string, args?: Record<string, unknown>) => Promise<string | null | undefined>;
669
+ }
670
+ /**
671
+ * Build a `loadSkill`-style tool for an Agent that defers content fetch
672
+ * to a caller-provided `load` function. The engine stays governance-
673
+ * agnostic: production deployments wire `load` to call a governance
674
+ * gateway; tests can inline an in-memory loader; CLIs can read from disk.
675
+ *
676
+ * The returned tool accepts a single `args?: Record<string, unknown>`
677
+ * parameter — keep it permissive so end-user skills can describe their
678
+ * own argument shape inside the skill body without re-engineering this
679
+ * helper.
680
+ *
681
+ * @example
682
+ * ```ts
683
+ * const skillTool = defineSkillTool({
684
+ * skillId: "pdf-processing",
685
+ * description: "Loads the PDF processing skill body",
686
+ * load: async (id, args) => `# Skill body for ${id}: ${JSON.stringify(args)}`,
687
+ * });
688
+ * ```
689
+ */
690
+ declare const defineSkillTool: (config: SkillToolConfig) => Tool;
691
+ /**
692
+ * Catalog entry for {@link skillDiscoveryMessage}. Mirrors the Agent
693
+ * Skills spec's tier-1 metadata shape (~100 tokens per skill) — `name`
694
+ * + `description` only.
695
+ */
696
+ interface SkillCatalogEntry {
697
+ skillId: string;
698
+ description: string;
699
+ /** Optional display name; defaults to `skillId` when absent. */
700
+ displayName?: string;
701
+ }
702
+ /**
703
+ * Build a system-reminder string listing every available skill so the
704
+ * LLM can discover what's loadable before deciding to call `loadSkill`.
705
+ *
706
+ * Format follows the Agent Skills spec's recommended catalog wrapping —
707
+ * `<available_skills>` with one `<skill>` block per entry plus an
708
+ * instruction footer telling the model when to call the loader.
709
+ *
710
+ * Returns an empty string when `skills` is empty, so callers can drop
711
+ * the result into their system prompt unconditionally.
712
+ */
713
+ declare const skillDiscoveryMessage: (skills: ReadonlyArray<SkillCatalogEntry>) => string;
714
+
649
715
  /**
650
716
  * Configuration for creating a tool.
651
717
  *
@@ -696,4 +762,4 @@ interface ToolConfig<TParams extends z.ZodType, TReturn = unknown> {
696
762
  */
697
763
  declare const tool: <TParams extends z.ZodType, TReturn>(config: ToolConfig<TParams, TReturn>) => Tool;
698
764
 
699
- export { Agent, type AgentConfig, type AgentConfigEvent, type AgentDelegationEvent, type AgentErrorEvent, type AgentEvent, type AgentEventBase, type AgentEventPayload, type AgentEventType, type AgentInterruptEvent, type AgentKillEvent, type AgentLLMCallEvent, type AgentLifecycleEvent, type AgentLike, type AgentNotificationEvent, type AgentRef, type AgentState, type AgentStructuredOutputCompleteEvent, type AgentThoughtEvent, type AgentToolCallEvent, type AgentTranscriptInitEvent, type ExecutionContext, type GenerateParams, type GenerateResponse, type GlobalConfig, type GoogleModelConfig, type GoogleModelId, type HumanDecision, type Interrupt, type Kernel, type KernelSignal, KrakenError, type LogLevel, type Message, type Middleware, type MiddlewareContext, type Model, type ModelParams, type ModelString, type OpenAIModelId, OutputValidationError, ProviderError, type RetryConfig, type RunOptions, type RunResult, type RunnerResponse, type SpawnSpec, type StreamChunk, type TeamAccessor, type ThinkingLevel, type Tool, type ToolCall, type ToolConfig, type ToolDefinition, ToolError, ToolInputValidationError, type ToolResult, type TransitionRecord, type Usage, ValidationError, configure, defineKernel, formatEvent, google, mock, openai, tool };
765
+ export { Agent, type AgentConfig, type AgentConfigEvent, type AgentDelegationEvent, type AgentErrorEvent, type AgentEvent, type AgentEventBase, type AgentEventPayload, type AgentEventType, type AgentInterruptEvent, type AgentKillEvent, type AgentLLMCallEvent, type AgentLifecycleEvent, type AgentLike, type AgentNotificationEvent, type AgentRef, type AgentState, type AgentStructuredOutputCompleteEvent, type AgentThoughtEvent, type AgentToolCallEvent, type AgentTranscriptInitEvent, type ExecutionContext, type GenerateParams, type GenerateResponse, type GlobalConfig, type GoogleModelConfig, type GoogleModelId, type HumanDecision, type Interrupt, type Kernel, type KernelSignal, KrakenError, type LogLevel, type Message, type Middleware, type MiddlewareContext, type Model, type ModelParams, type ModelString, type OpenAIModelId, OutputValidationError, ProviderError, type RetryConfig, type RunOptions, type RunResult, type RunnerResponse, type SkillCatalogEntry, type SkillToolConfig, type SpawnSpec, type StreamChunk, type TeamAccessor, type ThinkingLevel, type Tool, type ToolCall, type ToolConfig, type ToolDefinition, ToolError, ToolInputValidationError, type ToolResult, type TransitionRecord, type Usage, ValidationError, configure, defineKernel, defineSkillTool, formatEvent, google, mock, openai, skillDiscoveryMessage, tool };
package/dist/index.js CHANGED
@@ -73,17 +73,12 @@ import * as z from "zod";
73
73
  var delegationSchema = z.object({
74
74
  task: z.string().describe("The task to delegate to this team member")
75
75
  });
76
- var createDelegationTools = (team, propagatedOptions, childRunIds) => team.map((member) => ({
76
+ var createDelegationTools = (team, propagatedOptions) => team.map((member) => ({
77
77
  name: `delegate_to_${member.name}`,
78
78
  description: member.description ?? `Delegate a task to ${member.name}`,
79
79
  execute: async (args) => {
80
80
  const { task } = delegationSchema.parse(args);
81
- const childRunId = childRunIds?.get(member.name)?.shift();
82
- const childOptions = {
83
- ...propagatedOptions,
84
- ...childRunId ? { runId: childRunId } : {}
85
- };
86
- const result = await member.run([{ role: "user", content: task }], childOptions);
81
+ const result = await member.run([{ role: "user", content: task }], propagatedOptions);
87
82
  if (result.status === "complete") return result.output;
88
83
  throw new Error(`Delegation to ${member.name} was interrupted`);
89
84
  },
@@ -392,18 +387,11 @@ var createRunner = (config2) => {
392
387
  for (const { tc } of approved) {
393
388
  if (tc.name.startsWith("delegate_to_")) {
394
389
  const targetName = tc.name.replace("delegate_to_", "");
395
- const childRunId = crypto.randomUUID();
396
390
  emitter.emit({
397
391
  type: "delegation",
398
- childRunId,
392
+ childRunId: crypto.randomUUID(),
399
393
  childAgentName: targetName
400
394
  });
401
- const queue = options?._childRunIds?.get(targetName);
402
- if (queue) {
403
- queue.push(childRunId);
404
- } else {
405
- options?._childRunIds?.set(targetName, [childRunId]);
406
- }
407
395
  }
408
396
  }
409
397
  }
@@ -591,7 +579,6 @@ var Agent = class {
591
579
  }
592
580
  const resolvedThinkingLevel = options?.thinkingLevel ?? this.config.thinkingLevel;
593
581
  const resolvedMaxOutputTokens = options?.maxOutputTokens ?? this.config.maxOutputTokens;
594
- const childRunIds = /* @__PURE__ */ new Map();
595
582
  if (this.config.team?.length) {
596
583
  const propagated = {
597
584
  middleware: options?.middleware,
@@ -602,7 +589,7 @@ var Agent = class {
602
589
  ...resolvedThinkingLevel ? { thinkingLevel: resolvedThinkingLevel } : {},
603
590
  ...resolvedMaxOutputTokens != null ? { maxOutputTokens: resolvedMaxOutputTokens } : {}
604
591
  };
605
- const delegationTools = createDelegationTools(this.config.team, propagated, childRunIds);
592
+ const delegationTools = createDelegationTools(this.config.team, propagated);
606
593
  allTools.push(...delegationTools);
607
594
  }
608
595
  const runner = createRunner({
@@ -619,7 +606,7 @@ var Agent = class {
619
606
  responseSchema: this.config.outputSchema ? z2.toJSONSchema(this.config.outputSchema, { target: "draft-2020-12" }) : void 0,
620
607
  logLevel: this.config.logLevel
621
608
  });
622
- const result = await runner.run(messages, { ...options, runId, _childRunIds: childRunIds });
609
+ const result = await runner.run(messages, { ...options, runId });
623
610
  if (result.status === "complete" && this.config.outputSchema) {
624
611
  const validated = await this.produceStructuredOutput(result, options);
625
612
  options?.onEvent?.({
@@ -788,6 +775,9 @@ var mock = (config2) => {
788
775
  };
789
776
  };
790
777
 
778
+ // src/skills.ts
779
+ import * as z4 from "zod";
780
+
791
781
  // src/tool.ts
792
782
  import * as z3 from "zod";
793
783
  var tool = (config2) => {
@@ -827,6 +817,43 @@ Hint: The LLM provided arguments that don't match the tool's parameter schema. T
827
817
  }
828
818
  };
829
819
  };
820
+
821
+ // src/skills.ts
822
+ var skillContentBlock = (skillId, content) => `<skill_content name="${skillId}">
823
+ ${content}
824
+ </skill_content>`;
825
+ var notLoadedMessage = (skillId) => `<skill_load_failed name="${skillId}">no content returned by loader</skill_load_failed>`;
826
+ var defineSkillTool = (config2) => {
827
+ const toolDescription = config2.description ?? (config2.displayName ? `Load the "${config2.displayName}" skill body.` : `Load the "${config2.skillId}" skill body.`);
828
+ return tool({
829
+ name: `load_skill_${config2.skillId.replace(/-/g, "_")}`,
830
+ description: toolDescription,
831
+ parameters: z4.object({
832
+ args: z4.record(z4.string(), z4.unknown()).optional().describe("Optional arguments forwarded to the skill loader.")
833
+ }),
834
+ execute: async ({ args }) => {
835
+ const content = await config2.load(config2.skillId, args);
836
+ if (content === null || content === void 0) {
837
+ return notLoadedMessage(config2.skillId);
838
+ }
839
+ return skillContentBlock(config2.skillId, content);
840
+ }
841
+ });
842
+ };
843
+ var skillDiscoveryMessage = (skills) => {
844
+ if (skills.length === 0) return "";
845
+ const blocks = skills.map((s) => {
846
+ const name = s.displayName ?? s.skillId;
847
+ return ` <skill id="${s.skillId}" name="${name}">${s.description}</skill>`;
848
+ });
849
+ return [
850
+ "<available_skills>",
851
+ ...blocks,
852
+ "</available_skills>",
853
+ "",
854
+ "If a skill is relevant to the user's request, call its load tool to retrieve the full skill body before relying on it."
855
+ ].join("\n");
856
+ };
830
857
  export {
831
858
  Agent,
832
859
  KrakenError,
@@ -837,9 +864,11 @@ export {
837
864
  ValidationError,
838
865
  configure,
839
866
  defineKernel,
867
+ defineSkillTool,
840
868
  formatEvent,
841
869
  google,
842
870
  mock,
843
871
  openai,
872
+ skillDiscoveryMessage,
844
873
  tool
845
874
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kraken-ai",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "Kraken AI SDK: a very lightweight, fully-typed multi-model AI agent framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -14,16 +14,16 @@
14
14
  }
15
15
  },
16
16
  "devDependencies": {
17
- "@google/genai": "^1.48.0",
18
- "@types/node": "^25.5.2",
17
+ "@google/genai": "^1.50.1",
18
+ "@types/node": "^25.6.0",
19
19
  "tsup": "^8.5.1",
20
20
  "tsx": "^4.21.0",
21
- "typescript": "^6.0.2",
22
- "vitest": "^4.1.3",
21
+ "typescript": "^6.0.3",
22
+ "vitest": "^4.1.5",
23
23
  "zod": "^4.3.6"
24
24
  },
25
25
  "peerDependencies": {
26
- "@google/genai": ">=1.0.0",
26
+ "@google/genai": "^1.50.1",
27
27
  "zod": "^4.0.0"
28
28
  },
29
29
  "peerDependenciesMeta": {