mirror of
https://github.com/vercel/eve.git
synced 2026-09-20 05:35:39 +08:00
fix(eve): keep agent router models serializable
Signed-off-by: Casey Gowrie <ctgowrie@gmail.com>
This commit is contained in:
@@ -426,7 +426,7 @@ const target = await auto({
|
||||
});
|
||||
```
|
||||
|
||||
`message` and `agents` are required. `model`, `instructions`, and `abortSignal` are optional; `model` accepts an evaluation model instance or ID, and the helper defaults to `typesafe-ai/jev` and `"Which subagent should handle this task?"`. It trims descriptions, ignores empty entries, skips evaluation for a sole candidate, and returns the selected agent name.
|
||||
`message` and `agents` are required. `model`, `instructions`, and `abortSignal` are optional; `model` accepts a serializable evaluation model ID, and the helper defaults to `typesafe-ai/jev` and `"Which subagent should handle this task?"`. It trims descriptions, ignores empty entries, skips evaluation for a sole candidate, and returns the selected agent name.
|
||||
|
||||
`ctx.agents` is a replay-stable metadata snapshot taken when the workflow starts. In a top-level root workflow, `ctx.agents.agent` always represents the root-copy target and carries the root's authored `description` when provided. The snapshot also includes declared agents hidden from the parent model with `tool: false` or `disableTool()`, but exposes no model definitions, credentials, or callbacks. A delegated root copy omits `agent`, so `agentRouter()` cannot select another root copy recursively. Invocation still checks each target's availability through `ctx.agent()`.
|
||||
|
||||
@@ -440,7 +440,7 @@ import { agentRouter } from "eve/tools/agent-router";
|
||||
export default agentRouter();
|
||||
```
|
||||
|
||||
Pass `model` or `instructions` to customize the provided router. Because factory options become durable workflow configuration, `model` must be a serializable model ID; use `auto()` directly when you need an evaluation model instance:
|
||||
Pass `model` or `instructions` to customize the provided router:
|
||||
|
||||
```ts title="agent/tools/agent.ts"
|
||||
import { agentRouter } from "eve/tools/agent-router";
|
||||
@@ -451,6 +451,8 @@ export default agentRouter({
|
||||
});
|
||||
```
|
||||
|
||||
Both `auto()` and `agentRouter()` accept model IDs only because their configuration crosses durable workflow boundaries. To use a live evaluation model instance, write your own `"use step"` helper and create or import the model inside that step instead of passing it as an argument.
|
||||
|
||||
Its input is `{ message: string, outputSchema?: object }`. `agentRouter()` ignores entries without a non-empty description. With two or more described targets, it sends the message and effective descriptions to JEV, then invokes the selected name through `ctx.agent()`. It invokes a sole target without evaluation and forwards an optional `outputSchema` unchanged. In a top-level root session, the candidates include the root-copy `agent`; delegated root copies and declared subagent contexts include only their declared targets.
|
||||
|
||||
When an authored tool accepts a JSON Schema supplied by the model, represent that input with a permissive object such as `z.looseObject({})`. Avoid `z.record(z.string(), z.json())`: its generated JSON Schema uses `propertyNames`, which OpenAI does not support. Validate the supplied value at the point where your tool consumes it.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"kind": "eve-extension-capability-contract",
|
||||
"capability": "tool",
|
||||
"epoch": 53,
|
||||
"sha256": "cec3f516eccdd2bf4b08ec7bc75048b29cb50233e9effa983707b232b3282455",
|
||||
"sha256": "f591e6389c338895fbb342d81d10507d1b3374fef6a5ce2dd90efe84e9fdd856",
|
||||
"exports": [
|
||||
"AgentRouterAutoOptions",
|
||||
"AgentRouterInput",
|
||||
|
||||
@@ -46,7 +46,7 @@ export async function auto({
|
||||
if (typeof instructions !== "string" || instructions.trim().length === 0) {
|
||||
throw new Error("agentRouter auto requires non-empty instructions when provided.");
|
||||
}
|
||||
if (typeof model === "string" && model.trim().length === 0) {
|
||||
if (typeof model !== "string" || model.trim().length === 0) {
|
||||
throw new Error("agentRouter auto requires a non-empty model ID when provided.");
|
||||
}
|
||||
const criteria = Object.fromEntries(
|
||||
|
||||
@@ -1,22 +1,11 @@
|
||||
import { z } from "#compiled/zod/index.js";
|
||||
import type { JsonObject } from "#shared/json.js";
|
||||
import type { evaluate } from "#ai/evaluate.js";
|
||||
|
||||
export { auto, executeAgentRouterTool } from "#execution/tools/agent-router-workflow.js";
|
||||
|
||||
export const AGENT_ROUTER_TOOL_DESCRIPTION =
|
||||
"Route a task to the best available subagent based on each subagent's declared description.";
|
||||
|
||||
export interface AgentRouterAutoOptions {
|
||||
readonly abortSignal?: AbortSignal;
|
||||
readonly agents: Readonly<Record<string, string>>;
|
||||
/** Instructions used to select an agent. */
|
||||
readonly instructions?: string;
|
||||
readonly message: string;
|
||||
/** Evaluation model instance or ID. Defaults to TypeSafe Jev. */
|
||||
readonly model?: Parameters<typeof evaluate>[0]["model"];
|
||||
}
|
||||
|
||||
export interface AgentRouterOptions {
|
||||
/** Instructions used to select an agent. */
|
||||
readonly instructions?: string;
|
||||
@@ -24,6 +13,12 @@ export interface AgentRouterOptions {
|
||||
readonly model?: string;
|
||||
}
|
||||
|
||||
export interface AgentRouterAutoOptions extends AgentRouterOptions {
|
||||
readonly abortSignal?: AbortSignal;
|
||||
readonly agents: Readonly<Record<string, string>>;
|
||||
readonly message: string;
|
||||
}
|
||||
|
||||
export interface AgentRouterInput {
|
||||
readonly message: string;
|
||||
readonly outputSchema?: JsonObject;
|
||||
|
||||
@@ -184,6 +184,10 @@ describe("agentRouter", () => {
|
||||
error: "agentRouter auto requires a non-empty model ID when provided.",
|
||||
options: { agents: { researcher: "Research" }, message: "Research", model: "" },
|
||||
},
|
||||
{
|
||||
error: "agentRouter auto requires a non-empty model ID when provided.",
|
||||
options: { agents: { researcher: "Research" }, message: "Research", model: {} },
|
||||
},
|
||||
{
|
||||
error: 'agentRouter auto requires a string description for agent "researcher".',
|
||||
options: { agents: { researcher: 42 }, message: "Research" },
|
||||
|
||||
Reference in New Issue
Block a user