Skip to content

feat(eve): support authored agent router selectors - #3532

Closed
ctgowrie wants to merge 9 commits into
mainfrom
feat/agent-router-auto-helper
Closed

ctgowrie wants to merge 9 commits into
mainfrom
feat/agent-router-auto-helper

Conversation

@ctgowrie

@ctgowrie ctgowrie commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Custom workflow routers currently have to repeat agentRouter()'s JEV selection logic. This exports reusable auto() from eve/tools/agent-router/auto for authored routing steps, including steps that import a live evaluation model, and adds agentRouter({ select }) for plugging an authored durable selector into the provided router. Without select, agentRouter() keeps its internal default step and optional serializable model-ID/instruction overrides; its exact zero-argument API remains supported.

The workflow guide presents three choices in order: write the full evaluate() step, call auto() inside an authored step, or use agentRouter() with its default or a custom selector. Custom selector names are validated against the described candidate map before invocation.

Validation

The full eve unit suite passed 8,987 tests with 1 skipped. Deterministic e2e coverage passed 5/5 gates with two candidates: agentRouter({ select }) reconstructs the authored selector step, that step imports a live evaluation model and calls auto(), and the selected root copy is invoked. eve and fixture typecheck, docs, lint, invariants, and retained extension-contract checks also pass.

Checklist

  • This change was requested or approved by a maintainer
  • I ran the relevant checks from CONTRIBUTING.md
  • I added tests and documentation where relevant
  • I added a changeset if this touches the published eve package
  • DCO sign-off passes for every commit (git commit --signoff)

Diff size

Docs — 3 files · +50 / -3

Documents the full custom pattern, reusable auto() logic, and provided router with default or authored selector as three distinct choices, plus release-facing behavior.

Implementation — 11 files · +216 / -37

Extracts reusable selection logic, carries authored selectors by stable step ID, reconstructs selector proxies in the workflow body, validates options/results, keeps model-auth code behind the step boundary, and exports the new subpath and types.

Tests — 10 files · +289 / -3

Covers defaults, live and string evaluation models, filtering, validation, selector transport and result checks, deterministic workflow bundling/execution, and retained tool capability compatibility.

@github-actions

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

Bundle + Package Summary: apps/fixtures/weather-agent

Key takeaways

  • No notable deltas vs main (d004e6d).

Delta vs main (d004e6d)

Area Metric Baseline Current Delta
Package Packed tarball 8.57 MB 8.57 MB +2.0 kB ⚠️
Package Unpacked publish size 31.94 MB 31.95 MB +8.5 kB ⚠️
Package Installed footprint 78.07 MB 78.07 MB +8.5 kB ⚠️
Package Published files 3759 3767 +8
Package Installed files 7719 7727 +8
Package Installed package instances 33 33 0
Package Distinct installed package names 32 32 0
Package Installed dependency edges 51 51 0
Package Installed optional peer edges 8 8 0
Runtime Unique function payloads 2 2 0
Runtime Total function bytes 22.06 MB 22.08 MB +17.4 kB ⚠️
Runtime Public routes 18 18 0
Changed function payloads vs main (d004e6d) (2)
Function Status Baseline Current Delta Route changes
functions/__server.func changed 11.03 MB 11.04 MB +8.7 kB ⚠️ none
functions/.well-known/workflow/v1/flow.func changed 11.03 MB 11.04 MB +8.7 kB ⚠️ none

eve init install

Metric Baseline Current Delta
Installed footprint 116.29 MB 116.30 MB +8.5 kB ⚠️
Installed packages 98 98 0
dependencies 4 4 0
devDependencies 2 2 0
Dependency package bytes 49.38 MB 49.39 MB +8.5 kB ⚠️
devDependency package bytes 5.04 MB 5.04 MB 0 B ➖
Build Metadata
  • Preset: vercel
  • Nitro: nitro@3.0.260903-beta
  • Output directory: apps/fixtures/weather-agent/.vercel/output
  • Build metadata timestamp: 2026-09-21T01:58:21.858Z
  • Route aliases: 18 public, 1 internal (19 total aliases)
  • Vercel routes in config: 21
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.63.0
  • Package directory: packages/eve
  • Tarball: 8.57 MB (eve-0.63.0.tgz)
  • Unpacked payload: 31.95 MB across 3767 published files
  • Installed footprint: 78.07 MB across 7727 installed files
  • Installed root package: 31.30 MB
  • Installed dependencies: 46.78 MB
  • Installed package instances: 33
  • Distinct installed package names: 32
  • Installed dependency edges: 51
  • Installed optional peer edges: 8
  • Runtime dependencies: 2
  • Peer dependencies: 6 (5 optional)

Installed footprint is measured from an isolated temporary npm install of the packed tarball.
Graph metrics read only package.json files in package directories directly beneath a node_modules boundary, including nested boundaries. Each directory is one package instance; distinct names come from those manifests. Dependency edges count each unique name in dependencies or optionalDependencies per instance; optional peer edges count peerDependencies marked optional.

Heavy installed dependencies

  • eve: 31.30 MB (40.1%)
  • @rolldown/binding-linux-x64-gnu: 19.10 MB (24.5%)
  • ai: 7.62 MB (9.8%)
  • zod: 6.67 MB (8.5%)
  • undici: 3.51 MB (4.5%)
Publish payload breakdown
Published file size
🔴 dist/src/compiled/shadcn-registry/index.js       [#############...........] 9.70 MB 30.4%
🟠 dist/src/compiled/@photon-ai/chat-adapter-ime... [###.....................] 2.29 MB 7.2%
🟠 dist/src/compiled/@ai-sdk/code-mode/index.js     [#.......................] 1.03 MB 3.2%
🟡 dist/src/compiled/@vercel/blob/index.js          [#.......................] 902.9 kB 2.8%
🟡 dist/src/compiled/_chunks/workflow/signal-exi... [#.......................] 514.5 kB 1.6%
🔴 Other published files                            [########################] 17.51 MB 54.8%
Installed footprint breakdown
Installed package size
🔴 eve                             [########################] 31.30 MB 40.1%
🔴 @rolldown/binding-linux-x64-gnu [###############.........] 19.10 MB 24.5%
🔴 ai                              [######..................] 7.62 MB 9.8%
🔴 zod                             [#####...................] 6.67 MB 8.5%
🟠 undici                          [###.....................] 3.51 MB 4.5%
🟠 nitro                           [#.......................] 1.89 MB 2.4%
🔴 Other installed packages        [######..................] 7.98 MB 10.2%
Runtime dependencies (2)
Package Range Notes
nitro 3.0.260903-beta
undici 8.9.0
Peer dependencies (6)
Package Range Notes
@opentelemetry/api ^1.0.0 optional peer
ai catalog:
braintrust ^3.0.0 optional peer
dd-trace ^6.13.0 optional peer
just-bash ^3.1.0 optional peer
microsandbox ^0.5.0 optional peer
eve init install drill-down

eve init install details

  • Command: eve init my-agent
  • Package manager: npm
  • Installed footprint: 116.30 MB across 9621 installed files
  • Installed packages: 98 total (92 transitive-only)
  • dependencies: 4 direct packages totaling 49.39 MB
  • devDependencies: 2 direct packages totaling 5.04 MB
  • Other transitive package files: 61.86 MB

Installed footprint is measured from an isolated temporary eve init my-agent using the current packed eve tarball.

Heavy installed dependencies

  • eve: 31.30 MB (26.9%)
  • @typescript/typescript-linux-x64: 27.95 MB (24.0%)
  • @rolldown/binding-linux-x64-gnu: 19.10 MB (16.4%)
  • zod: 10.29 MB (8.8%)
  • ai: 7.62 MB (6.6%)
Installed footprint breakdown
Installed package size
🔴 eve                              [########################] 31.30 MB 26.9%
🔴 @typescript/typescript-linux-x64 [#####################...] 27.95 MB 24.0%
🔴 @rolldown/binding-linux-x64-gnu  [###############.........] 19.10 MB 16.4%
🔴 zod                              [########................] 10.29 MB 8.8%
🔴 ai                               [######..................] 7.62 MB 6.6%
🟠 undici                           [###.....................] 3.51 MB 3.0%
🔴 Other installed packages         [#############...........] 16.53 MB 14.2%
dependencies (4)
Package Range Installed size Share
@vercel/connect 2.2.0 188.7 kB 0.2%
ai ^7.0.105 7.62 MB 6.6%
eve file:eve-0.63.0.tgz 31.30 MB 26.9%
zod 4.5.4 10.29 MB 8.8%
devDependencies (2)
Package Range Installed size Share
@types/node 24.x 2.54 MB 2.2%
typescript 7.0.2 2.50 MB 2.1%
Function Drill-Down

Payload Size Graph

Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func     [########################] 11.04 MB 50.0%
🔴 functions/__server.func                         [########################] 11.04 MB 50.0%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 11.04 MB
Metric Value
Public routes /.well-known/workflow/v1/flow
Runtime nodejs24.x
Handler index.mjs
Payload 11.04 MB
Function files 11.04 MB across 117 files
Traced dependencies 0 B
Signal 🟠 Bundled file index.mjs is 2.89 MB (26.2%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 index.mjs                        [##############..........] 2.89 MB 26.2%
🟡 _libs/undici.mjs                 [#####...................] 980.8 kB 8.9%
🟡 _chunks/sandbox.mjs              [####....................] 809.9 kB 7.3%
🟡 _chunks/chatgpt-model.mjs        [###.....................] 700.3 kB 6.3%
🟡 _chunks/signal-exit-B9U6kH7R.mjs [###.....................] 616.2 kB 5.6%
🔴 Other bundled files              [########################] 5.04 MB 45.6%

🧾 Vercel Config

{
  "handler": "index.mjs",
  "launcherType": "Nodejs",
  "shouldAddHelpers": false,
  "supportsResponseStreaming": true,
  "runtime": "nodejs24.x",
  "maxDuration": "max",
  "experimentalTriggers": [
    {
      "type": "queue/v2beta",
      "topic": "__eve776561746865722d6167656e74_wkf_workflow_*",
      "consumer": "default",
      "retryAfterSeconds": 5,
      "initialDelaySeconds": 0
    }
  ],
  "environment": {
    "WORKFLOW_PRECONDITION_GUARD": "1"
  }
}

🟠 functions/__server.func • 17 public routes, 1 internal alias • 11.04 MB
Metric Value
Public routes /
/.well-known/workflow/v1/webhook/[token]
/eve/v1/activity/[token]
/eve/v1/callback/[token]
/eve/v1/connections/[name]/callback/[attemptId]/[token]
/eve/v1/connections/[name]/callback/[token]
/eve/v1/health
/eve/v1/info
/eve/v1/session
/eve/v1/session/[parentSessionId]/subagents/[callId]/[childSessionId]/stream
/eve/v1/session/[sessionId]
/eve/v1/session/[sessionId]/cancel
/eve/v1/session/[sessionId]/clear
/eve/v1/session/[sessionId]/compact
/eve/v1/session/[sessionId]/reset
/eve/v1/session/[sessionId]/stream
/eve/v1/task-input/[token]
Internal aliases /__server
Runtime nodejs24.x
Handler index.mjs
Payload 11.04 MB
Function files 11.04 MB across 117 files
Traced dependencies 0 B
Signal 🟠 Bundled file index.mjs is 2.89 MB (26.2%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 index.mjs                        [##############..........] 2.89 MB 26.2%
🟡 _libs/undici.mjs                 [#####...................] 980.8 kB 8.9%
🟡 _chunks/sandbox.mjs              [####....................] 809.9 kB 7.3%
🟡 _chunks/chatgpt-model.mjs        [###.....................] 700.3 kB 6.3%
🟡 _chunks/signal-exit-B9U6kH7R.mjs [###.....................] 616.2 kB 5.6%
🔴 Other bundled files              [########################] 5.04 MB 45.6%

🧾 Vercel Config

{
  "handler": "index.mjs",
  "launcherType": "Nodejs",
  "shouldAddHelpers": false,
  "supportsResponseStreaming": true,
  "runtime": "nodejs24.x"
}

Build Timing: e2e/fixtures/agent-tools-sandbox

This is an informational timing measurement inside eve build, from preflight through publication. Output-size measurement and profile writing are excluded.

Build mode: deployable Vercel build with sandbox template prewarm included.

  • Build pipeline: 3.86 s -> 3.92 s (+53.0 ms) vs main (d004e6d).
  • Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `main (d004e6d)`
Phase Baseline Current Delta
extension.check 14.1 ms 0.4 ms -13.7 ms
project.resolve 0.4 ms 0.3 ms -0.1 ms
workspace.create 0.6 ms 0.5 ms -0.1 ms
host.prepare 533.9 ms 599.6 ms +65.7 ms
vercel.service-prefix.resolve 2.1 ms 2.5 ms +0.4 ms
nitro.create 294.2 ms 288.0 ms -6.2 ms
sandbox.prewarm 294.3 ms 291.6 ms -2.7 ms
nitro.cache.prepare 0.2 ms 0.3 ms +0.1 ms
nitro.prepare 0.7 ms 0.8 ms +0.1 ms
nitro.public-assets 0.7 ms 0.7 ms 0.0 ms
nitro.prerender 0.4 ms 0.5 ms +0.1 ms
nitro.bundle 2.66 s 2.68 s +12.0 ms
nitro.cache.write 0.4 ms 0.3 ms -0.1 ms
vercel.workflow-function.materialize 49.9 ms 48.1 ms -1.8 ms
agent-summary.emit 0.6 ms 0.6 ms 0.0 ms
nitro.close 0.1 ms 0.1 ms 0.0 ms
output.publish 3.5 ms 3.1 ms -0.4 ms
workspace.remove 2.3 ms 2.1 ms -0.2 ms

readonly instructions?: string;
readonly message: string;
/** Evaluation model instance or ID. Defaults to TypeSafe Jev. */
readonly model?: Parameters<typeof evaluate>[0]["model"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Do not accept live model instances across this step boundary. auto() is itself a "use step" function, so this options object is serialized when callers use it from the documented workflow body. Evaluation-model instances contain executable doEvaluate behavior and cannot cross that durable boundary, so the documented model: providerModel path fails before routing. The unit test calls auto() directly, and the E2E fixture has one candidate and returns before evaluation, so neither exercises this path. Please restrict and validate this as a non-empty model ID like AgentRouterOptions, then remove the instance claim from the docs, or redesign the API so the model is constructed inside the registered step from serializable configuration.

throw new Error("agentRouter auto requires a non-empty model ID when provided.");
}
const criteria = Object.fromEntries(
Object.entries(agents).flatMap(([name, description]) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Validate candidate names at this public boundary. auto() now accepts a user-authored map, but only its descriptions are validated. For example, { " ": "Research" } reaches the sole-candidate fast path and returns " ", while ctx.agent() rejects any target whose trimmed name is empty. Please reject empty or whitespace-only keys while building criteria, before either the fast path or evaluation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I don't think this is likely I think you do want to check this and figure out what backtracking could look like.

Comment thread docs/tools/workflows.mdx Outdated
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:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Describe the configured evaluator. Now that agentRouter({ model }) supports a custom model, the behavior text below is inaccurate when it says the router always sends the request to JEV. Please describe this as the configured evaluation model, with JEV as the default.

@vercel

vercel Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
eve-docs Ready Ready Preview, v0 Sep 21, 2026 1:58am UTC
eve-pkg Ready Ready Preview, v0 Sep 21, 2026 1:58am UTC

Comment thread packages/eve/src/execution/tools/agent-router.ts
throw new Error("agentRouter auto requires a non-empty model ID when provided.");
}
const criteria = Object.fromEntries(
Object.entries(agents).flatMap(([name, description]) => {

@vercel vercel Bot Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalizeAgents() validates agent descriptions but never validates the agent name keys, so an empty/whitespace-only key survives and is returned as a route target by the public auto() helper, deferring the failure to a confusing downstream error.

Fix on Vercel

Signed-off-by: Casey Gowrie <ctgowrie@gmail.com>
Signed-off-by: Casey Gowrie <ctgowrie@gmail.com>
@ctgowrie ctgowrie changed the title feat(eve): expose agent router auto helper feat(eve): support authored agent router selectors Sep 20, 2026
…o-helper

Signed-off-by: Casey Gowrie <ctgowrie@gmail.com>

# Conflicts:
#	packages/eve/extension-contracts/reports/tool/v53.json
#	packages/eve/src/compiler/extension-compatibility.ts
Signed-off-by: Casey Gowrie <ctgowrie@gmail.com>
Signed-off-by: Casey Gowrie <ctgowrie@gmail.com>
@vercel
vercel Bot temporarily deployed to Preview – eve-pkg September 20, 2026 13:31 Inactive
Signed-off-by: Casey Gowrie <ctgowrie@gmail.com>
Signed-off-by: Casey Gowrie <ctgowrie@gmail.com>
@ctgowrie

Copy link
Copy Markdown
Collaborator Author

Do not think this should be part of the public API

@ctgowrie ctgowrie closed this Sep 21, 2026

This branch was successfully deployed

2 active deployments
Preview – eve-docs — 6e9701d7 Deployed Sep 21, 2026 by vercel[bot]
Preview – eve-pkg — 6e9701d7 Deployed Sep 21, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants