Skip to content

fix(eve): negotiate supported older remote protocols before admission - #5346

Merged
OwenKephart merged 5 commits into
v27/lab-fixesfrom
owen/eve-v27-fleet-confidence
Oct 26, 2026
Merged

OwenKephart merged 5 commits into
v27/lab-fixesfrom
owen/eve-v27-fleet-confidence

Conversation

@OwenKephart

@OwenKephart OwenKephart commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The api fleet's new parents could not use deployed eve@0.83.2 remote agents. This draft makes that pairing work end to end, and fixes a hang in concurrent ctx.agent sends. Three changes, each in its own commit:

  1. Protocol negotiation. An eve@0.83.2 receiver 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.
  2. Protocol-2 human input (new parent → 0.83.2 child). 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:
    • The two protocol-2 callback kinds are read as v27 relay facts, using the same v26 mappings the history reader applies (moved to protocol/v26-interactions.ts).
    • Answers go to the child as v26 inputResponses (requestId), keeping the forwarded responder. earlierProtocol now survives on the relay binding and in stored relay state, so replays keep the right form.
    • The child still settles its own approvals and sign-ins, and still decides who may answer. An answer it turns away leaves the approval open.
    • The child never reports how a question or budget prompt settles, so the parent settles those once the child accepts the answer. A Stop already settled by the parent is not settled twice.
    • The parent marks the callback URL it negotiates (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.
    • Protocol 1 task callbacks are still refused.
  3. Concurrent send ordering. Concurrent ctx.agent sends 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-fixes branch. 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

  • Real mixed-version loopback. A parent on this build and a child on the published eve@0.83.2 package, both as isolated CLI servers. Deterministic fixture models; no external tools, credentials or production state.
    • Approve: the parent mirrors the child's approval with its asked call (guard), and settles accepted. The child's tool runs as the forwarded responder (current/initiator: alice).
    • Deny: settles declined, and the child's tool reports "Tool execution was denied." without running.
    • Question: the child's ask_question receives {"answer":"iad1","status":"answered"}, and the parent's mirror settles accepted.
    • Cancel while the child waits: the mirror is withdrawn (asker-ended), the call is interrupted, and nothing is approved.
    • Before this change, the same approval failed TASK_FAILED with Remote input callback failed with HTTP 400.
  • Regression check on the same build. Terminal results in both directions pass. Current-protocol scenarios pass: authorized child reads, Alice → Bob task reuse with Alice kept as initiator, a v27 approval relayed and answered through the parent, and turn-scoped cancellation.
  • Unit tests.
    • Translation tests run protocol-2 bodies through the real relay/routeAnswer transitions.
    • Route tests cover marked, unmarked, malformed and protocol-1 bodies.
    • Also covered: the inputResponses answer wire, URL marking during negotiation and continuation, and stored-relay protocol persistence.
    • Ordering regressions reproduce the hang (admission seed → right → left) on the base.
  • Results:
    • Full unit tier: 851 files, 8,103 passed, 1 skipped.
    • Integration: 2,099 passed. Its one failure is a model-auth test that only fails because the sandbox sets ANTHROPIC_BASE_URL; it passes 4/4 with that unset.
    • Scenario: 513 passed. Its 5 failures (eve init, Nitro pack, real-shell bash) fail identically on the untouched base 28de6fc8f.
    • Typecheck, scoped oxfmt/oxlint and docs:check (109 pages) are clean.
  • This is not a deployed v/Slack journey.

Checklist

  • 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)

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>
@vercel

vercel Bot commented Oct 26, 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 Oct 26, 2026 5:33pm UTC
eve-pkg Ready Ready Preview, v0 Oct 26, 2026 5:33pm UTC

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

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

Key takeaways

  • No notable deltas vs v27/lab-fixes (28de6fc).

Delta vs v27/lab-fixes (28de6fc)

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;

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.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

960d290 implements the protocol-2 input relay, so negotiating protocol 2 now covers it.

  • The callback route reads subagent-input-request and subagent-authorization-event as v27 relay facts, using the same v26 mappings as the history reader.
  • Answers go back as v26 inputResponses with 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.

Comment thread packages/eve/src/execution/agent-sessions/remote.ts Outdated
Comment thread docs/guides/remote-agents.md Outdated
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),

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.

A protocol-2 budget prompt preserves the Stop option ID stop, but parent routing only recognizes deny, so choosing Stop leaves the parent turn running and records the prompt as accepted.

Fix on Vercel

@OwenKephart

Copy link
Copy Markdown
Contributor Author

Retested the published immutable build 960d2902a496401dd9953f72de1eb408081540bf against the original standalone concurrent-task reproducer. The requested ordering fix works in these checks:

  • Unchanged original batch: 8/8 passed. Strengthened batch: 60/60 passed, all with the three deliveries sharing one child turn. Admission stayed seed → left → right; all three parent calls completed and every root became idle. The previous builds 619ea4ef and 28de6fc8 each had a hang in an eight-attempt batch. These use a deterministic model with real durable workflows, local World, HTTP client, and public streams—not a mocked admission function.
  • Sequential sends still map to separate turns; overlapping sends share a turn; fan-out stays separate. agentCallActivity retains the expected causal links/shared-turn ownership. A deliberately lagging read prefix remains pending rather than looking settled.
  • Separate loopback parent on this build → child on published npm eve@0.83.2: approval, denial, question/answer, and whole-parent-turn cancellation pass. The approved fixture returns its local-dev current/initiator; denial returns the tool-denied result. The question returns iad1/answered. Whole-turn cancellation settles the actual turn as cancelled and interrupts the mirrored input—distinct from merely accepting a cancel command.
  • Following the old remote through SessionStore correctly reports child observation unavailable / unsupported while retaining the completed authoritative parent result.
  • Real retained 0.80.1 recordings still read through the new server, preserving text/runtime metadata, cursor suffixes, and prompt ownerless-follow termination.

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>
@OwenKephart
OwenKephart merged commit 2727354 into v27/lab-fixes Oct 26, 2026
138 of 143 checks passed
@OwenKephart
OwenKephart deleted the owen/eve-v27-fleet-confidence branch October 26, 2026 17:29

This branch was successfully deployed

2 active deployments
Preview – eve-docs — 27273544 Deployed Oct 26, 2026 by vercel[bot]
Preview – eve-pkg — 27273544 Deployed Oct 26, 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.

1 participant