diff --git a/apps/nextjs/src/features/WaggleDance/types/WaggleDanceAgentExecutor.ts b/apps/nextjs/src/features/WaggleDance/types/WaggleDanceAgentExecutor.ts index e5fe2614..8be7e73a 100644 --- a/apps/nextjs/src/features/WaggleDance/types/WaggleDanceAgentExecutor.ts +++ b/apps/nextjs/src/features/WaggleDance/types/WaggleDanceAgentExecutor.ts @@ -1,4 +1,5 @@ import { type MutableRefObject } from "react"; +import { type JsonSpec } from "langchain/tools"; import { stringify } from "yaml"; import { @@ -16,6 +17,7 @@ import planTasks from "../utils/planTasks"; import { sleep } from "../utils/sleep"; import { mapAgentSettingsToCreationProps, + type ExecuteRequestBody, type GraphDataState, type WaggleDanceResult, } from "./types"; @@ -67,9 +69,19 @@ class WaggleDanceAgentExecutor { this.taskResults = {}; this.error = null; const initialNode = rootPlanNode(this.goalPrompt); + let agentProtocolOpenAPISpec: JsonSpec | undefined; + + try { + agentProtocolOpenAPISpec = (await ( + await fetch("/api/ap") + ).json()) as JsonSpec; + } catch { + console.error("Failed to fetch agent protocol spec"); + } + void (async () => { try { - const result = await this.planAndSetDAG(); + const result = await this.planAndSetDAG(agentProtocolOpenAPISpec); console.debug("done planning"); if (this.error) { return; @@ -200,7 +212,9 @@ class WaggleDanceAgentExecutor { }; } - async planAndSetDAG(): Promise { + async planAndSetDAG( + agentProtocolOpenAPISpec?: JsonSpec, + ): Promise { const creationProps = mapAgentSettingsToCreationProps( this.agentSettings["plan"], ); @@ -213,6 +227,7 @@ class WaggleDanceAgentExecutor { log: this.log, injectAgentPacket: this.injectAgentPacket, abortSignal: this.abortController.signal, + agentProtocolOpenAPISpec, }); // Call the check methods here @@ -258,7 +273,7 @@ class WaggleDanceAgentExecutor { const creationProps = mapAgentSettingsToCreationProps( this.agentSettings["execute"], ); - const executeRequest = { + const executeRequest: ExecuteRequestBody = { goalPrompt: this.goalPrompt, goalId: this.goalId, executionId: this.executionId, diff --git a/apps/nextjs/src/features/WaggleDance/types/types.ts b/apps/nextjs/src/features/WaggleDance/types/types.ts index f57494aa..94572d0f 100644 --- a/apps/nextjs/src/features/WaggleDance/types/types.ts +++ b/apps/nextjs/src/features/WaggleDance/types/types.ts @@ -1,5 +1,6 @@ // WaggleDance/types.ts import { type Dispatch, type SetStateAction } from "react"; +import { type JsonSpec } from "langchain/tools"; import { type AgentSettings, @@ -75,6 +76,7 @@ export interface BaseRequestBody { creationProps: ModelCreationProps; goalId: string; goalPrompt: string; + agentProtocolOpenAPISpec?: JsonSpec; } export interface RefineRequestBody { diff --git a/apps/nextjs/src/features/WaggleDance/utils/planTasks.ts b/apps/nextjs/src/features/WaggleDance/utils/planTasks.ts index 65ca290f..a701843a 100644 --- a/apps/nextjs/src/features/WaggleDance/utils/planTasks.ts +++ b/apps/nextjs/src/features/WaggleDance/utils/planTasks.ts @@ -1,5 +1,7 @@ // features/WaggleDance/utils/planTasks.ts +import { type JsonSpec } from "langchain/tools"; + import { type DraftExecutionGraph, type DraftExecutionNode } from "@acme/db"; import { @@ -26,6 +28,7 @@ export type PlanTasksProps = { task: DraftExecutionNode, dag: DraftExecutionGraph, ) => Promise; + agentProtocolOpenAPISpec?: JsonSpec; }; export default async function planTasks({ @@ -38,6 +41,7 @@ export default async function planTasks({ injectAgentPacket, startFirstTask, abortSignal, + agentProtocolOpenAPISpec, }: PlanTasksProps): Promise { const intervalHandler = new PlanUpdateIntervalHandler(100); // update at most every... const parseWorker = new Worker(new URL("./parseWorker.ts", import.meta.url)); @@ -48,7 +52,14 @@ export default async function planTasks({ let partialDAG: DraftExecutionGraph = dag; let hasFirstTaskStarted = false; - const data = { goalPrompt, goalId, executionId, creationProps }; + const data = { + goalPrompt, + goalId, + executionId, + creationProps, + agentProtocolOpenAPISpec, + }; + // TODO: merge w/ api.execution.createPlan const res = await fetch("/api/agent/plan", { method: "POST", headers: { "Content-Type": "application/json" }, diff --git a/apps/nextjs/src/pages/api/agent/plan.ts b/apps/nextjs/src/pages/api/agent/plan.ts index 52d9f5d6..5d2a92a2 100644 --- a/apps/nextjs/src/pages/api/agent/plan.ts +++ b/apps/nextjs/src/pages/api/agent/plan.ts @@ -39,6 +39,7 @@ export default async function PlanStream(req: NextRequest) { goalPrompt: parsedGoalPrompt, goalId: parsedGoalId, executionId: parsedExecutionId, + agentProtocolOpenAPISpec, } = (await req.json()) as PlanRequestBody; goalPrompt = parsedGoalPrompt; goalId = parsedGoalId; @@ -92,6 +93,7 @@ export default async function PlanStream(req: NextRequest) { goalId!, abortController.signal, `${goalId}_${executionId}`, + agentProtocolOpenAPISpec, ); if (planResult instanceof Error) { diff --git a/packages/agent/src/strategy/callExecutionAgent.ts b/packages/agent/src/strategy/callExecutionAgent.ts index edf77eb9..318c0b18 100644 --- a/packages/agent/src/strategy/callExecutionAgent.ts +++ b/packages/agent/src/strategy/callExecutionAgent.ts @@ -22,6 +22,7 @@ import { import { type AgentStep } from "langchain/schema"; import { AbortError } from "redis"; import { stringify as jsonStringify } from "superjson"; +import { type JsonSpec } from "langchain/tools"; import { parse as yamlParse, stringify as yamlStringify } from "yaml"; import { z } from "zod"; @@ -80,6 +81,7 @@ export async function callExecutionAgent(creation: { contentType: "application/json" | "application/yaml"; abortSignal: AbortSignal; namespace: string; + agentProtocolOpenAPISpec?: JsonSpec; geo?: Geo; }): Promise { const { @@ -93,6 +95,7 @@ export async function callExecutionAgent(creation: { abortSignal, namespace, contentType, + agentProtocolOpenAPISpec, geo, } = creation; const callbacks = creationProps.callbacks; @@ -152,6 +155,7 @@ export async function callExecutionAgent(creation: { isCriticism, taskObj.id, returnType, + agentProtocolOpenAPISpec, geo, ); diff --git a/packages/agent/src/strategy/callPlanningAgent.ts b/packages/agent/src/strategy/callPlanningAgent.ts index 80981ff7..d9ebe6ce 100644 --- a/packages/agent/src/strategy/callPlanningAgent.ts +++ b/packages/agent/src/strategy/callPlanningAgent.ts @@ -2,6 +2,7 @@ import { encodingForModel, type Tiktoken } from "js-tiktoken"; import { LLMChain } from "langchain/chains"; +import { type JsonSpec } from "langchain/tools"; import { parse as jsonParse, stringify as jsonStringify } from "superjson"; import { parse as yamlParse, stringify as yamlStringify } from "yaml"; @@ -26,6 +27,7 @@ export async function callPlanningAgent( goalId: string, signal: AbortSignal, namespace: string, + agentProtocolOpenAPISpec?: JsonSpec, returnType: "YAML" | "JSON" = "YAML", ): Promise { const tags = [ @@ -43,6 +45,7 @@ export async function callPlanningAgent( false, rootPlanId, returnType, + agentProtocolOpenAPISpec, ); const prompt = createPlanPrompt({ goalPrompt, diff --git a/packages/agent/src/utils/skills.ts b/packages/agent/src/utils/skills.ts index 52e72726..d7656142 100644 --- a/packages/agent/src/utils/skills.ts +++ b/packages/agent/src/utils/skills.ts @@ -5,12 +5,14 @@ import { SearchApi, SerpAPI, WolframAlphaTool, + type JsonSpec, type SearchApiParameters, type StructuredTool, } from "langchain/tools"; import { WebBrowser } from "langchain/tools/webbrowser"; import cca2Map from "../lib/cca2Map.json"; +import { AgentProtocolToolkit } from "../skills/AgentProtocolSkill"; import requestUserHelpSkill from "../skills/requestUserHelpSkill"; import type Geo from "./Geo"; import { type AgentPromptingMethod } from "./llms"; @@ -216,6 +218,7 @@ function createSkills( isCriticism: boolean, taskId: string, returnType: "YAML" | "JSON", + agentProtocolOpenAPISpec?: JsonSpec, geo?: Geo, ): StructuredTool[] { const tools = [ @@ -263,6 +266,10 @@ function createSkills( ); } + if (agentProtocolOpenAPISpec) { + const toolkit = new AgentProtocolToolkit(agentProtocolOpenAPISpec, llm, {}); + tools.push(...toolkit.tools); + } return tools as StructuredTool[]; }