diff --git a/package.json b/package.json index a0f8afb..7c13876 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ }, "dependencies": { "express": "^4.21.1", - "inngest": "3.27.6-pr-776.2", + "inngest": "^3.28.0", "openai-zod-to-json-schema": "^1.0.3", "zod": "^3.23.8" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 65ad14b..e2b57ce 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^4.21.1 version: 4.21.1 inngest: - specifier: 3.27.6-pr-776.2 - version: 3.27.6-pr-776.2(express@4.21.1)(typescript@5.7.2) + specifier: ^3.28.0 + version: 3.28.0(express@4.21.1)(typescript@5.7.2) openai-zod-to-json-schema: specifier: ^1.0.3 version: 1.0.3(zod@3.23.8) @@ -866,8 +866,8 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - inngest@3.27.6-pr-776.2: - resolution: {integrity: sha512-hod0BjJkKKSuA5hyIwMuPqaVBKM4UY9zZwU7kJPV+BCmhEOf0oX0Rr4x5eLffjwTzCXWWi4HuNtBXZpmNF58tQ==} + inngest@3.28.0: + resolution: {integrity: sha512-7myzcPkX+A0PakUMwczIdDqt5lpHEgVqeK0N8IUcONjajlt/g1sk+yjZ88ER8SxoJWCFFoAV04NJdZN9ka1N1A==} engines: {node: '>=14'} peerDependencies: '@sveltejs/kit': '>=1.27.3' @@ -2477,7 +2477,7 @@ snapshots: inherits@2.0.4: {} - inngest@3.27.6-pr-776.2(express@4.21.1)(typescript@5.7.2): + inngest@3.28.0(express@4.21.1)(typescript@5.7.2): dependencies: '@types/debug': 4.1.12 canonicalize: 1.0.8 diff --git a/src/index.ts b/src/index.ts index 1b32a09..42a9b2f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ export * from "./agent"; export * from "./model"; export * from "./network"; +export * from "./networkRun"; export * from "./state"; export * from "./types"; export * from "./util"; diff --git a/src/network.ts b/src/network.ts index 685459e..a0cc19a 100644 --- a/src/network.ts +++ b/src/network.ts @@ -1,13 +1,8 @@ import { type AiAdapter } from "inngest"; import { z } from "zod"; -import { - type Agent, - type RoutingAgent, - createRoutingAgent, - createTool, -} from "./agent"; +import { createRoutingAgent, type Agent, type RoutingAgent } from "./agent"; import { NetworkRun } from "./networkRun"; -import { type InferenceResult, State } from "./state"; +import { State, type InferenceResult } from "./state"; import { type MaybePromise } from "./util"; /** @@ -131,76 +126,78 @@ export class Network { * It is no set model and so relies on the presence of a default model in the * network or being explicitly given one. */ -export const defaultRoutingAgent = createRoutingAgent({ - name: "Default routing agent", - - description: - "Selects which agents to work on based off of the current prompt and input.", - - lifecycle: { - onRoute: ({ result }) => { - const tool = result.toolCalls[0]; - if (!tool) { - return; - } - if (typeof tool.content === "string") { - return [tool.content]; - } - return; - }, - }, - - tools: [ - // This tool does nothing but ensure that the model responds with the - // agent name as valid JSON. - createTool({ - name: "select_agent", - description: - "select an agent to handle the input, based off of the current conversation", - parameters: z - .object({ - name: z - .string() - .describe("The name of the agent that should handle the request"), - }) - .strict(), - handler: ({ name }, { network }) => { - if (!network) { - throw new Error( - "The routing agent can only be used within a network of agents", - ); - } - - if (typeof name !== "string") { - throw new Error("The routing agent requested an invalid agent"); +let defaultRoutingAgent: RoutingAgent | undefined; +export const getDefaultRoutingAgent = () => { + defaultRoutingAgent ??= createRoutingAgent({ + name: "Default routing agent", + + description: + "Selects which agents to work on based off of the current prompt and input.", + + lifecycle: { + onRoute: ({ result }) => { + const tool = result.toolCalls[0]; + if (!tool) { + return; } - - const agent = network.agents.get(name); - if (agent === undefined) { - throw new Error( - `The routing agent requested an agent that doesn't exist: ${name}`, - ); + if (typeof tool.content === "string") { + return [tool.content]; } + return; + }, + }, - // This returns the agent name to call. The default routing functon - // schedules this agent by inpsecting this name via the tool call output. - return agent.name; + tools: [ + // This tool does nothing but ensure that the model responds with the + // agent name as valid JSON. + { + name: "select_agent", + description: + "select an agent to handle the input, based off of the current conversation", + parameters: z + .object({ + name: z + .string() + .describe("The name of the agent that should handle the request"), + }) + .strict(), + handler: ({ name }, { network }) => { + if (!network) { + throw new Error( + "The routing agent can only be used within a network of agents", + ); + } + + if (typeof name !== "string") { + throw new Error("The routing agent requested an invalid agent"); + } + + const agent = network.agents.get(name); + if (agent === undefined) { + throw new Error( + `The routing agent requested an agent that doesn't exist: ${name}`, + ); + } + + // This returns the agent name to call. The default routing functon + // schedules this agent by inpsecting this name via the tool call output. + return agent.name; + }, }, - }), - ], + ], - tool_choice: "select_agent", + tool_choice: "select_agent", - system: async ({ network }): Promise => { - if (!network) { - throw new Error( - "The routing agent can only be used within a network of agents", - ); - } + system: async ({ network }): Promise => { + if (!network) { + throw new Error( + "The routing agent can only be used within a network of agents", + ); + } - const agents = await network?.availableAgents(); + const agents = await network?.availableAgents(); - return `You are the orchestrator between a group of agents. Each agent is suited for a set of specific tasks, and has a name, instructions, and a set of tools. + return `You are the orchestrator between a group of agents. Each agent is suited for a set of specific tasks, and has a name, instructions, and a set of tools. The following agents are available: @@ -224,8 +221,11 @@ Follow the set of instructions: Your aim is to thoroughly complete the request, thinking step by step, choosing the right agent based off of the context. `; - }, -}); + }, + }); + + return defaultRoutingAgent; +}; export namespace Network { export type Constructor = { diff --git a/src/networkRun.ts b/src/networkRun.ts index 93fa4cc..706150f 100644 --- a/src/networkRun.ts +++ b/src/networkRun.ts @@ -1,5 +1,5 @@ import { RoutingAgent, type Agent } from "./agent"; -import { defaultRoutingAgent, Network } from "./network"; +import { getDefaultRoutingAgent, Network } from "./network"; import { type State } from "./state"; export class NetworkRun extends Network { @@ -118,7 +118,7 @@ export class NetworkRun extends Network { ); } if (!router) { - router = defaultRoutingAgent; + router = getDefaultRoutingAgent(); } if (router instanceof RoutingAgent) { return await this.getNextAgentsViaRoutingAgent(router, input);