Repository navigation
fix(eve): negotiate supported older remote protocols before admission - #5346
Conversation
Preserve documented result-only delegation to protocol-2 receivers. Negotiate once only after explicit pre-admission refusal; keep uncertain work non-retryable. Signed-off-by: owenkephart <owen.kephart@vercel.com>
Bundle + Package Summary:
|
| Area | Metric | Baseline | Current | Delta |
|---|---|---|---|---|
| Package | Packed tarball | 7.82 MB | 7.83 MB | +5.3 kB |
| Package | Unpacked publish size | 27.29 MB | 27.31 MB | +19.5 kB |
| Package | Installed footprint | 75.61 MB | 75.63 MB | +19.5 kB |
| Package | Published files | 4356 | 4360 | +4 |
| Package | Installed files | 8349 | 8353 | +4 |
| Package | Installed package instances | 34 | 34 | 0 |
| Package | Distinct installed package names | 32 | 32 | 0 |
| Package | Installed dependency edges | 51 | 51 | 0 |
| Package | Installed optional peer edges | 17 | 17 | 0 |
| Runtime | Unique function payloads | 2 | 2 | 0 |
| Runtime | Total function bytes | 21.27 MB | 21.31 MB | +40.4 kB |
| Runtime | Public routes | 18 | 18 | 0 |
Changed function payloads vs v27/lab-fixes (28de6fc) (2)
| Function | Status | Baseline | Current | Delta | Route changes |
|---|---|---|---|---|---|
functions/__server.func |
changed | 10.63 MB | 10.66 MB | +20.2 kB |
none |
functions/.well-known/workflow/v1/flow.func |
changed | 10.64 MB | 10.66 MB | +20.2 kB |
none |
eve init install
| Metric | Baseline | Current | Delta |
|---|---|---|---|
| Installed footprint | 113.99 MB | 114.01 MB | +19.5 kB |
| Installed packages | 97 | 97 | 0 |
| dependencies | 4 | 4 | 0 |
| devDependencies | 2 | 2 | 0 |
| Dependency package bytes | 45.69 MB | 45.71 MB | +19.5 kB |
| devDependency package bytes | 5.11 MB | 5.11 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-10-26T17:33:20.554Z
- 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.83.2 - Package directory:
packages/eve - Tarball: 7.83 MB (
eve-0.83.2.tgz) - Unpacked payload: 27.31 MB across 4360 published files
- Installed footprint: 75.63 MB across 8353 installed files
- Installed root package: 27.31 MB
- Installed dependencies: 48.32 MB
- Installed package instances: 34
- Distinct installed package names: 32
- Installed dependency edges: 51
- Installed optional peer edges: 17
- Runtime dependencies: 2
- Peer dependencies: 15 (14 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: 27.31 MB (36.1%)@rolldown/binding-linux-x64-gnu: 19.89 MB (26.3%)ai: 8.37 MB (11.1%)zod: 6.15 MB (8.1%)undici: 3.58 MB (4.7%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/shadcn-registry/index.js [#####...................] 3.85 MB 14.1%
🟠 dist/src/compiled/@photon-ai/chat-adapter-ime... [###.....................] 2.29 MB 8.4%
🟠 dist/src/compiled/run/index.js [#.......................] 1.00 MB 3.7%
🟡 dist/src/compiled/@vercel/blob/index.js [#.......................] 604.9 kB 2.2%
🟡 dist/src/compiled/_chunks/workflow/undici-D-I... [#.......................] 521.9 kB 1.9%
🔴 Other published files [########################] 19.04 MB 69.7%
Installed footprint breakdown
Installed package size
🔴 eve [########################] 27.31 MB 36.1%
🔴 @rolldown/binding-linux-x64-gnu [#################.......] 19.89 MB 26.3%
🔴 ai [#######.................] 8.37 MB 11.1%
🔴 zod [#####...................] 6.15 MB 8.1%
🟠 undici [###.....................] 3.58 MB 4.7%
🟠 nitro [##......................] 1.89 MB 2.5%
🔴 Other installed packages [#######.................] 8.44 MB 11.2%
Runtime dependencies (2)
| Package | Range | Notes |
|---|---|---|
nitro |
3.0.260903-beta |
|
undici |
8.10.2 |
Peer dependencies (15)
| Package | Range | Notes |
|---|---|---|
@linqapp/sdk |
^0.47.1 |
optional peer |
@nuxt/kit |
^4.0.0 |
optional peer |
@nuxt/schema |
^4.0.0 |
optional peer |
@opentelemetry/api |
^1.0.0 |
optional peer |
@vercel/connect |
^2.5.2 |
optional peer |
ai |
catalog: |
|
braintrust |
^3.0.0 |
optional peer |
chat |
^4.42.0 |
optional peer |
dd-trace |
^6.13.0 |
optional peer |
just-bash |
^3.6.0 |
optional peer |
next |
^16.0.0 |
optional peer |
react |
^19.0.0 |
optional peer |
svelte |
^5.0.0 |
optional peer |
vite |
^8.3.1 |
optional peer |
vue |
^3.5.0 |
optional peer |
eve init install drill-down
eve init install details
- Command:
eve init my-agent - Package manager:
npm - Installed footprint: 114.01 MB across 10270 installed files
- Installed packages: 97 total (91 transitive-only)
- dependencies: 4 direct packages totaling 45.71 MB
- devDependencies: 2 direct packages totaling 5.11 MB
- Other transitive package files: 63.18 MB
Installed footprint is measured from an isolated temporary eve init my-agent using the current packed eve tarball.
Heavy installed dependencies
@typescript/typescript-linux-x64: 27.95 MB (24.5%)eve: 27.31 MB (24.0%)@rolldown/binding-linux-x64-gnu: 19.89 MB (17.4%)zod: 9.76 MB (8.6%)ai: 8.37 MB (7.3%)
Installed footprint breakdown
Installed package size
🔴 @typescript/typescript-linux-x64 [########################] 27.95 MB 24.5%
🔴 eve [#######################.] 27.31 MB 24.0%
🔴 @rolldown/binding-linux-x64-gnu [#################.......] 19.89 MB 17.4%
🔴 zod [########................] 9.76 MB 8.6%
🔴 ai [#######.................] 8.37 MB 7.3%
🟠 undici [###.....................] 3.58 MB 3.1%
🔴 Other installed packages [###############.........] 17.16 MB 15.1%
dependencies (4)
| Package | Range | Installed size | Share |
|---|---|---|---|
@vercel/connect |
2.5.2 |
276.3 kB | 0.2% |
ai |
^7.0.137 |
8.37 MB | 7.3% |
eve |
file:eve-0.83.2.tgz |
27.31 MB | 24.0% |
zod |
4.5.4 |
9.76 MB | 8.6% |
devDependencies (2)
| Package | Range | Installed size | Share |
|---|---|---|---|
@types/node |
24.x |
2.61 MB | 2.3% |
typescript |
7.0.2 |
2.50 MB | 2.2% |
Function Drill-Down
Payload Size Graph
Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func [########################] 10.66 MB 50.0%
🔴 functions/__server.func [########################] 10.66 MB 50.0%
Top Function Payloads
🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 10.66 MB
| Metric | Value |
|---|---|
| Public routes | /.well-known/workflow/v1/flow |
| Runtime | nodejs24.x |
| Handler | index.mjs |
| Payload | 10.66 MB |
| Function files | 10.66 MB across 124 files |
| Traced dependencies | 0 B |
| Signal | 🟠 Bundled file _chunks/vercel.web.mjs is 2.59 MB (24.4%) |
🟠 🔎 Dependency Analysis
📦 Bundled files:
Bundled file size
🟠 _chunks/vercel.web.mjs [#############...........] 2.59 MB 24.4%
🟡 _libs/undici.mjs [#####...................] 994.5 kB 9.3%
🟡 _chunks/sandbox2.mjs [####....................] 815.0 kB 7.6%
🟡 _chunks/compiled-artifacts-instrumentation.mjs [####....................] 730.7 kB 6.9%
🟡 _chunks/token-util-Bla5Z0G9.mjs [####....................] 704.5 kB 6.6%
🔴 Other bundled files [########################] 4.82 MB 45.2%
🧾 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 • 10.66 MB
| Metric | Value |
|---|---|
| Public routes | //.well-known/workflow/v1/webhook/[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]/descendants/stream/eve/v1/session/[sessionId]/reset/eve/v1/session/[sessionId]/stream/eve/v1/session/[sessionId]/stubs |
| Internal aliases | /__server |
| Runtime | nodejs24.x |
| Handler | index.mjs |
| Payload | 10.66 MB |
| Function files | 10.66 MB across 124 files |
| Traced dependencies | 0 B |
| Signal | 🟠 Bundled file _chunks/vercel.web.mjs is 2.59 MB (24.4%) |
🟠 🔎 Dependency Analysis
📦 Bundled files:
Bundled file size
🟠 _chunks/vercel.web.mjs [#############...........] 2.59 MB 24.4%
🟡 _libs/undici.mjs [#####...................] 994.5 kB 9.3%
🟡 _chunks/sandbox2.mjs [####....................] 815.0 kB 7.6%
🟡 _chunks/compiled-artifacts-instrumentation.mjs [####....................] 730.7 kB 6.9%
🟡 _chunks/token-util-Bla5Z0G9.mjs [####....................] 704.5 kB 6.6%
🔴 Other bundled files [########################] 4.82 MB 45.2%
🧾 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.96 s -> 3.86 s (-103.0 ms) vs
v27/lab-fixes (28de6fc). - Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `v27/lab-fixes (28de6fc)`
| Phase | Baseline | Current | Delta |
|---|---|---|---|
extension.check |
9.9 ms | 20.1 ms | +10.2 ms |
project.resolve |
0.5 ms | 9.6 ms | +9.1 ms |
workspace.create |
0.7 ms | 1.1 ms | +0.4 ms |
host.prepare |
607.4 ms | 544.8 ms | -62.6 ms |
vercel.service-prefix.resolve |
2.0 ms | 2.1 ms | +0.1 ms |
nitro.create |
513.0 ms | 452.5 ms | -60.5 ms |
sandbox.prewarm |
510.2 ms | 570.4 ms | +60.2 ms |
nitro.cache.prepare |
0.3 ms | 0.2 ms | -0.1 ms |
nitro.prepare |
0.8 ms | 0.8 ms | 0.0 ms |
nitro.public-assets |
0.8 ms | 0.9 ms | +0.1 ms |
nitro.prerender |
0.5 ms | 0.6 ms | +0.1 ms |
nitro.bundle |
2.16 s | 2.11 s | -55.8 ms |
nitro.cache.write |
0.4 ms | 0.4 ms | 0.0 ms |
vercel.workflow-function.materialize |
56.0 ms | 56.8 ms | +0.8 ms |
agent-summary.emit |
0.7 ms | 0.7 ms | 0.0 ms |
connect-manifest.emit |
0.4 ms | 0.3 ms | -0.1 ms |
nitro.close |
0.1 ms | 0.1 ms | 0.0 ms |
output.publish |
3.6 ms | 3.7 ms | +0.1 ms |
workspace.remove |
2.8 ms | 3.0 ms | +0.2 ms |
| rejected.data.protocolVersion < REMOTE_AGENT_PROTOCOL_VERSION | ||
| ) { | ||
| // This protocol rejection precedes admission; an accepted or ambiguous response never negotiates a resend. | ||
| requestBody.protocolVersion = rejected.data.protocolVersion; |
There was a problem hiding this comment.
Sending protocolVersion: 2 here tells the older child that this caller speaks protocol 2 in full. That includes the protocol-2 input relay, which this caller doesn't implement.
In the published eve@0.83.2 (dist/src/execution/forward-session-input.js, same as main), a child whose caller is on its own version posts every input.requested, approval.candidate, authorization.required, etc. to the callback URL as kind: "subagent-input-request" / "subagent-authorization-event". When the response isn't ok, it throws Remote input callback failed with HTTP ${status}. This branch's callback route only knows subagent-interaction / turn.completed / turn.failed, so it answers 400 Unsupported callback kind.
So after this change, any tool approval, ask, or sign-in in a 0.83.2 child fails that child's turn. As far as I can tell from main's finalization.ts, the step retries and then the parent's call fails with Remote input callback failed with HTTP 400. There's no protocol or upgrade guidance, unlike the reverse direction (formatEarlierRemoteCallerInputError). Before this PR, that only happened to children already in flight during an upgrade (docs L245-249). Now it's the normal path for every negotiated call. I traced this from the code and haven't run it end to end. The cheapest check is your loopback pair with a 0.83.2 child tool that needs approval.
Suggestion: have handleSessionCallbackRequest recognize those two protocol-2 kinds and settle the pending call with a failed subagent-result that carries an upgrade message, the way formatEarlierRemoteChildStreamError does for streams. Then add a wire-boundary test. At minimum, the new docs paragraph should say what the parent sees in this case.
There was a problem hiding this comment.
Agreed; result-only negotiation must not be presented as a working old-input relay. 1506fc6 now documents the HTTP-400 failure explicitly. I am checking the actual 0.83.2 approval path with the loopback pair. I am not synthesizing a child terminal outcome/usage from an input request: that would claim a lifecycle boundary the child did not produce. Leaving this thread open for the safe failure/upgrade design rather than claiming the docs alone solve it. The api fleet remains on the approved base artifact, not this candidate.
There was a problem hiding this comment.
Confirmed with the actual loopback pair and published eve@0.83.2 child: requesting approval produces no parent interaction; the child step retries three times, then the parent agent call fails with TASK_FAILED / Remote input callback failed with HTTP 400. The parent delivery itself completes, so checking only delivery success would miss it. No approval was answered and the fixture tool has no external effect. This remains explicitly unsupported and this thread stays open; terminal-result negotiation is not a complete old-HITL solution.
There was a problem hiding this comment.
960d290 implements the protocol-2 input relay, so negotiating protocol 2 now covers it.
- The callback route reads
subagent-input-requestandsubagent-authorization-eventas v27 relay facts, using the same v26 mappings as the history reader. - Answers go back as v26
inputResponseswith the forwarded responder. - The child still settles its approvals and sign-ins, and an answer it turns away leaves the approval open. The parent settles questions and budget prompts once the child accepts the answer, because a protocol-2 child never reports how they settle.
- The negotiated callback URL is marked
eveRemoteProtocol=2, and only marked URLs are translated. A pre-v27 parent run's child therefore still fails visibly instead of hanging on a relay that run can't read.
Same loopback pair with the published eve@0.83.2 child:
- Approve: settles
accepted, and the tool runs as alice. - Deny: settles
declined, and the tool doesn't run. - Question: the answer reaches the child's
ask_question. - Cancel: the mirror is withdrawn and nothing is approved.
The v27 relay, task reuse and cancellation scenarios still pass. Leaving this thread for you to resolve.
Signed-off-by: owenkephart <owen.kephart@vercel.com>
A turn's reply settles the messages sent before the one it answers, which assumes the agent admits messages in the order their replies were registered. Concurrent sends ran their delivery steps concurrently, so the agent could admit them in another order; the turn then replied to a message that left a later-sent one unsettled, and the agent tool's serve loop, which awaits the newest message, never replied to its calls. Deliver each handle's messages one after another, in send order, without waiting for any turn's result, so steering still joins the running turn. Capture each message's auth, call, and lineage when it is sent, since the run's accessors follow the call it serves now. A replacement session is still announced once, before any delivery links to it. Signed-off-by: owenkephart <owen.kephart@vercel.com>
…ign-ins A parent that negotiates protocol 2 with a remote child now mirrors that child's input requests and returns their answers, rather than refusing its callbacks with HTTP 400 and failing the child's turn. - Read `subagent-input-request` and `subagent-authorization-event` as the v27 relay facts, using the v26 request/outcome/sign-in mappings the history reader already applies (moved to `protocol/v26-interactions.ts`). - Answer the child with v26 `inputResponses` (`requestId`), keeping the forwarded responder. Keep `earlierProtocol` on the relay binding and in stored relay state so answers stay in that form across replays. - The child settles its approvals and sign-ins; it never reports a question's or budget prompt's settlement, so the parent settles those once the child accepts the answer. Candidate outcomes map to response admission/settlement, so an answer the child turns away leaves the approval open. - Mark the callback URL of a negotiated child (`eveRemoteProtocol=2`) and read protocol-2 input only on a marked URL. A parent run from before v27 would drop the translated relay, so its child's input still fails visibly instead of waiting unseen. Protocol 1 task callbacks stay refused. Verified against published eve 0.83.2 children over loopback: approve (tool runs as the forwarded responder), deny (tool does not run), question (answer reaches the child), and cancel (mirror withdrawn, nothing approved). Current-protocol relay, reuse, and cancellation scenarios and both terminal-result directions still pass. Signed-off-by: owenkephart <owen.kephart@vercel.com>
| name: entry.action.toolName, | ||
| }, | ||
| }, | ||
| request: v26InteractionRequest(entry), |
|
Retested the published immutable build
No SDK patches, private imports, resends, or application-manufactured settlement. This is bounded local evidence, not a claim about deployed grants, multi-user forwarding, real sign-in, or old unmarked callbacks surviving a rollout. |
Name the agreed protocol on every callback URL, including protocol 3, so a later deployment always knows what a callback speaks. A URL that names no protocol comes from a parent run started before v27; an earlier child's approvals, questions, and sign-ins for it now pass through to that run unchanged instead of failing with HTTP 400 after the parent upgrades. Send a replay-stable idempotencyKey with each follow-up and set of answers to a protocol-3 child, named by the parent's durable step. The eve channel's message route accepts the key and derives the delivery ID from it, so a retry after a lost response is the same delivery with the same receipt. On real servers with the follow-up response dropped, the previous build admitted the follow-up twice (three child turns); this build admits it once (two turns) and the parent's child.sent receipt matches the child's delivery. Earlier protocols reject unknown fields, so they never receive the key. Answer a callback nothing waits on with 404 CALLBACK_NOT_PENDING. A child retries that answer briefly, since the parent may not yet have registered the reply hook, then logs it and keeps its session. Before, a dropped 202 for a delivered result made every retry 404 and ended the child's session failed although the parent had completed. Correct the upgrade order (callers before the remote agents they call) and record the protocol's invariants, extension points, and deferred items in research/remote-agent-protocol.md. Signed-off-by: owenkephart <owen.kephart@vercel.com>
Summary
The api fleet's new parents could not use deployed
eve@0.83.2remote agents. This draft makes that pairing work end to end, and fixes a hang in concurrentctx.agentsends. Three changes, each in its own commit:eve@0.83.2receiver rejects protocol 3 before admission and reports protocol 2. Negotiate once after that explicit refusal, with fresh credentials and the same callback and create-operation key. Never negotiate after acceptance, an ambiguous receipt, a rejection naming a session, or an unsupported version.0.83.2child). The child's approvals, questions and sign-ins used to be refused with HTTP 400, failing its turn. They now reach the parent's person, and answers go back in the form the child accepts:protocol/v26-interactions.ts).inputResponses(requestId), keeping the forwarded responder.earlierProtocolnow survives on the relay binding and in stored relay state, so replays keep the right form.eveRemoteProtocol=2) and reads protocol-2 input only on a marked URL. A parent run from before v27 would drop the translated relay. Its child's input therefore still fails visibly instead of waiting unseen.ctx.agentsends registered their reply waiters in send order, but deliveries could reach the child in another order. The newest call could then stay unsettled, leaving the serve loop waiting forever. Deliveries are now serialized per session handle. Turns are not, so steering still joins the running turn. Each send's auth and attribution are captured at send time.This draft targets #4855's
v27/lab-fixesbranch. It does not add child-stream access for earlier peers, human input for a protocol-2 caller of a v27 child, a rollout, or a change to the api fleet's approved SDK pin. No issue was created.Validation
eve@0.83.2package, both as isolated CLI servers. Deterministic fixture models; no external tools, credentials or production state.guard), and settlesaccepted. The child's tool runs as the forwarded responder (current/initiator: alice).declined, and the child's tool reports "Tool execution was denied." without running.ask_questionreceives{"answer":"iad1","status":"answered"}, and the parent's mirror settlesaccepted.asker-ended), the call is interrupted, and nothing is approved.TASK_FAILEDwithRemote input callback failed with HTTP 400.relay/routeAnswertransitions.inputResponsesanswer wire, URL marking during negotiation and continuation, and stored-relay protocol persistence.seed → right → left) on the base.ANTHROPIC_BASE_URL; it passes 4/4 with that unset.28de6fc8f.docs:check(109 pages) are clean.Checklist
evepackagegit commit --signoff)