diff --git a/.changeset/seven-beers-press.md b/.changeset/seven-beers-press.md new file mode 100644 index 0000000..b8fd2c0 --- /dev/null +++ b/.changeset/seven-beers-press.md @@ -0,0 +1,5 @@ +--- +"@inngest/agent-kit": patch +--- + +Use `@inngest/ai` and only optionally use step tooling diff --git a/examples/swebench/agents/planner.ts b/examples/swebench/agents/planner.ts index 4679c0d..e47bb3b 100644 --- a/examples/swebench/agents/planner.ts +++ b/examples/swebench/agents/planner.ts @@ -32,7 +32,7 @@ export const planningAgent = createAgent({ handler: async (plan, opts) => { // Store this in the function state for introspection in tracing. - await opts.step.run("plan created", () => plan); + await opts.step?.run("plan created", () => plan); opts.network?.state.kv.set("plan", plan); }, }), diff --git a/packages/agent-kit/package.json b/packages/agent-kit/package.json index 2cdfdf1..42806bb 100644 --- a/packages/agent-kit/package.json +++ b/packages/agent-kit/package.json @@ -46,6 +46,7 @@ }, "dependencies": { "@dmitryrechkin/json-schema-to-zod": "^1.0.0", + "@inngest/ai": "^0.0.0", "@modelcontextprotocol/sdk": "^1.1.1", "eventsource": "^3.0.2", "express": "^4.21.1", diff --git a/packages/agent-kit/src/adapters/anthropic.ts b/packages/agent-kit/src/adapters/anthropic.ts index 8087fcf..5f7211b 100644 --- a/packages/agent-kit/src/adapters/anthropic.ts +++ b/packages/agent-kit/src/adapters/anthropic.ts @@ -7,7 +7,7 @@ import { type AiAdapter, type Anthropic, type AnthropicAiAdapter, -} from "inngest"; +} from "@inngest/ai"; import { zodToJsonSchema } from "openai-zod-to-json-schema"; import { z } from "zod"; import { type AgenticModel } from "../model"; diff --git a/packages/agent-kit/src/adapters/index.ts b/packages/agent-kit/src/adapters/index.ts index 99e8396..5942033 100644 --- a/packages/agent-kit/src/adapters/index.ts +++ b/packages/agent-kit/src/adapters/index.ts @@ -1,4 +1,4 @@ -import { type AiAdapter, type AiAdapters } from "inngest"; +import { type AiAdapter, type AiAdapters } from "@inngest/ai"; import { type AgenticModel } from "../model"; import * as anthropic from "./anthropic"; import * as openai from "./openai"; diff --git a/packages/agent-kit/src/adapters/openai.ts b/packages/agent-kit/src/adapters/openai.ts index 97412c6..32ffeac 100644 --- a/packages/agent-kit/src/adapters/openai.ts +++ b/packages/agent-kit/src/adapters/openai.ts @@ -4,7 +4,7 @@ * @module */ -import { type AiAdapter, type OpenAi } from "inngest"; +import { type AiAdapter, type OpenAi } from "@inngest/ai"; import { zodToJsonSchema } from "openai-zod-to-json-schema"; import { type AgenticModel } from "../model"; import { diff --git a/packages/agent-kit/src/agent.ts b/packages/agent-kit/src/agent.ts index cbe61a6..2d09576 100644 --- a/packages/agent-kit/src/agent.ts +++ b/packages/agent-kit/src/agent.ts @@ -1,5 +1,15 @@ -import { type AiAdapter } from "inngest"; +import { + JSONSchemaToZod, + type JSONSchema, +} from "@dmitryrechkin/json-schema-to-zod"; +import { type AiAdapter } from "@inngest/ai"; +import { Client as MCPClient } from "@modelcontextprotocol/sdk/client/index.js"; +import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; +import { WebSocketClientTransport } from "@modelcontextprotocol/sdk/client/websocket.js"; import { type Transport } from "@modelcontextprotocol/sdk/shared/transport"; +import { ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js"; +import { EventSource } from "eventsource"; +import type { ZodType } from "zod"; import { createAgenticModelFromAiAdapter, type AgenticModel } from "./model"; import { NetworkRun } from "./networkRun"; import { @@ -8,20 +18,8 @@ import { type Message, type ToolResultMessage, } from "./state"; -import { type Tool, type MCP } from "./types"; +import { type MCP, type Tool } from "./types"; import { getStepTools, type AnyZodType, type MaybePromise } from "./util"; -// MCP -import { Client as MCPClient } from "@modelcontextprotocol/sdk/client/index.js"; -import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; -import { WebSocketClientTransport } from "@modelcontextprotocol/sdk/client/websocket.js"; -import { ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js"; -import { - type JSONSchema, - JSONSchemaToZod, -} from "@dmitryrechkin/json-schema-to-zod"; -import type { ZodType } from "zod"; -import { EventSource } from "eventsource"; - /** * createTool is a helper that properly types the input argument for a handler * based off of the Zod parameter types. @@ -392,16 +390,16 @@ export class Agent { server, tool: t, }, - handler: async ( - input: { [x: string]: unknown } | undefined, - opts - ) => { - const result = await opts.step.run(name, async () => { - return await client.callTool({ + handler: async (input: { [x: string]: unknown } | undefined) => { + const fn = () => + client.callTool({ name: t.name, arguments: input, }); - }); + + const step = await getStepTools(); + const result = await (step?.run(name, fn) ?? fn()); + return result.content; }, }); diff --git a/packages/agent-kit/src/model.ts b/packages/agent-kit/src/model.ts index 3a48cd7..49a676e 100644 --- a/packages/agent-kit/src/model.ts +++ b/packages/agent-kit/src/model.ts @@ -1,4 +1,4 @@ -import { type AiAdapter } from "inngest"; +import { type AiAdapter } from "@inngest/ai"; import { adapters } from "./adapters"; import { type Message } from "./state"; import { type Tool } from "./types"; @@ -41,12 +41,48 @@ export class AgenticModel { tools: Tool.Any[], tool_choice: Tool.Choice ): Promise { + const body = this.requestParser(this.#model, input, tools, tool_choice); + let result: AiAdapter.Input; + const step = await getStepTools(); - const result = (await step.ai.infer(stepID, { - model: this.#model, - body: this.requestParser(this.#model, input, tools, tool_choice), - })) as AiAdapter.Input; + if (step) { + result = (await step.ai.infer(stepID, { + model: this.#model, + body, + })) as AiAdapter.Input; + } else { + // Allow the model to mutate options and body for this call + const modelCopy = { ...this.#model }; + this.#model.onCall?.(modelCopy, body); + + const url = new URL(modelCopy.url || ""); + + const headers: Record = { + "Content-Type": "application/json", + }; + + // Make sure we handle every known format in `@inngest/ai`. + const formatHandlers: Record void> = { + "openai-chat": () => { + headers["Authorization"] = `Bearer ${modelCopy.authKey}`; + }, + anthropic: () => { + headers["x-api-key"] = modelCopy.authKey; + }, + }; + + formatHandlers[modelCopy.format as AiAdapter.Format](); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + result = await ( + await fetch(url, { + method: "POST", + headers, + body, + }) + ).json(); + } return { output: this.responseParser(result), raw: result }; } diff --git a/packages/agent-kit/src/models.ts b/packages/agent-kit/src/models.ts index dd85ef4..d90ff01 100644 --- a/packages/agent-kit/src/models.ts +++ b/packages/agent-kit/src/models.ts @@ -1 +1 @@ -export { openai, anthropic, gemini } from "inngest"; +export { anthropic, gemini, openai } from "@inngest/ai"; diff --git a/packages/agent-kit/src/network.ts b/packages/agent-kit/src/network.ts index 6087ad1..8a64d28 100644 --- a/packages/agent-kit/src/network.ts +++ b/packages/agent-kit/src/network.ts @@ -1,4 +1,4 @@ -import { type AiAdapter } from "inngest"; +import { type AiAdapter } from "@inngest/ai"; import { z } from "zod"; import { createRoutingAgent, diff --git a/packages/agent-kit/src/types.ts b/packages/agent-kit/src/types.ts index 0ce29e7..da9a7f8 100644 --- a/packages/agent-kit/src/types.ts +++ b/packages/agent-kit/src/types.ts @@ -1,13 +1,7 @@ -import { type GetStepTools, type Inngest } from "inngest"; import { type output as ZodOutput } from "zod"; import { type Agent } from "./agent"; import { type NetworkRun } from "./networkRun"; -import { - type AnyZodType, - type GenericizeFunctionsInObject, - type MaybePromise, - type SimplifyDeep, -} from "./util"; +import { type AnyZodType, type MaybePromise, type StepTools } from "./util"; export type Tool = { name: string; @@ -69,17 +63,5 @@ export namespace MCP { export type ToolHandlerArgs = { agent: Agent; network?: NetworkRun; - step: GetStepTools; + step?: StepTools; }; - -/** - * Represents step tooling from an Inngest client, purposefully genericized to - * allow for more flexible usage. - * - * Prefer use of `GetStepTools` in most cases, especially when you have access - * to a client. - */ -export type AnyStepTools = SimplifyDeep< - GenericizeFunctionsInObject> -> & - Record; diff --git a/packages/agent-kit/src/util.ts b/packages/agent-kit/src/util.ts index 6a0816f..a80b6bc 100644 --- a/packages/agent-kit/src/util.ts +++ b/packages/agent-kit/src/util.ts @@ -1,4 +1,4 @@ -import { getAsyncCtx } from "inngest/experimental"; +import { type AsyncContext, getAsyncCtx } from "inngest/experimental"; import { type ZodType } from "zod"; export type MaybePromise = T | Promise; @@ -29,18 +29,18 @@ export const stringifyError = (e: unknown): string => { }; /** - * Attempts to retrieve the step tools from the async context. If the context is - * not found, an error is thrown. + * Attempts to retrieve the step tools from the async context. */ -export const getStepTools = async () => { +export const getStepTools = async (): Promise< + AsyncContext["ctx"]["step"] | undefined +> => { const asyncCtx = await getAsyncCtx(); - if (!asyncCtx) { - throw new Error("Could not find Inngest step tooling in async context"); - } - return asyncCtx.ctx.step; + return asyncCtx?.ctx.step; }; +export type StepTools = Awaited>; + /** * Given an object `T`, return a new object where all keys with function types * as values are genericized. If the value is an object, recursively apply this diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 13c39c4..81ed079 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -107,6 +107,9 @@ importers: '@dmitryrechkin/json-schema-to-zod': specifier: ^1.0.0 version: 1.0.0 + '@inngest/ai': + specifier: ^0.0.0 + version: 0.0.0 '@modelcontextprotocol/sdk': specifier: ^1.1.1 version: 1.1.1