What problem are you trying to solve?
I'm building a gateway/orchestrator agent on eve — a chat front door that never does the work itself. It classifies an ask, authorizes it, dispatches it to an execution backend, and relays progress back to the humans in the thread. Backends are heterogeneous: Cursor Cloud Agents today, other eve agents alongside them, more later.
Every backend has to satisfy one executor contract:
interface ExecutorAdapter {
launch(descriptor): Promise<RunRef>;
steer(runId, message): Promise<{ delivered: boolean }>; // send another turn
status(runId): Promise<{ status, url?, ... }>;
abort(runId): Promise<{ aborted: boolean }>;
}
Cursor Cloud Agents satisfy all four. defineRemoteAgent satisfies only launch — a remote call is one turn in, one result out, and no handle/id allows for follow-ups, so the other three verbs have nowhere to go.
┌─────────────────────────────────┐
│ gateway agent (eve) │
│ classify · authorize · │
│ dispatch · relay │
└──────┬───────────────────┬──────┘
│ │
same contract│ │same contract
▼ ▼
┌──────────────────────────┐ ┌──────────────────────────┐
│ Cursor Cloud Agent │ │ eve agent │
│ (HTTP API + run ids) │ │ (defineRemoteAgent) │
├──────────────────────────┤ ├──────────────────────────┤
│ launch ✅ │ │ launch ✅ │
│ steer ✅ │ │ steer ❌ no handle │
│ status ✅ │ │ status ❌ no handle │
│ abort ✅ │ │ abort ❌ no handle │
└──────────────────────────┘ └──────────────────────────┘
the eve-native backend is the one
my gateway can't fully address
In the orchestrator code, I have a union whose second variant can't do three of the four verbs:
type ProfileEntry =
| { kind: "cloud"; adapter: ExecutorAdapter } // steerable, checkable, abortable
| { kind: "subagent"; tool: string }; // fire, wait, done
Everything downstream special-cases the second kind, including prose telling the model to complete the call itself because authored code can't.
Why this isn't the background-tasks story
#635 and #1084 give me detach and lifecycle — parent turn freed, status/cancel, completion notification. Both hit me too. Neither gives me a worker that stays a conversation: a task completes once, and I need to send turn 2 and turn 3 into the same worker with its context intact.
The distinguishing verb is steer, and it's the one users exercise. From a live multiplayer thread:
- Someone dispatches work to a remote agent.
- Two minutes later a different person adds a constraint.
- It has to reach the running worker, attributed, without restarting it.
- A third person asks how it's going and gets the worker's own narration back.
tasks/update isn't that, and cancel-and-relaunch discards accumulated context while doubling cost and side effects.
Proposed solution
A remote hop opens a durable session instead of consuming a turn:
TODAY parent turn ├──────── blocked ────────┤ ends
└─► remote: one turn in, one result out, gone
WANTED parent turn ├──┤ ends immediately
└─► worker session ──────────────────────────►
▲ ▲ ▲ ▲
send() status() stream() cancel()
│
turn 2, from a *different* human, mid-flight
// pseudo-code approach; likely more complex in practicum
const worker = await remoteWorker.open({ message: initialAsk });
await worker.send("From a teammate in the thread: also cover the EU case.");
const state = await worker.status();
for await (const e of worker.stream()) { /* relay to the thread */ }
await worker.cancel();
That's roughly POST /eve/v1/session/<id> plus the stream endpoint — machinery that already exists for external clients. The gap is that defineRemoteAgent doesn't expose it to a calling agent, so agent-to-agent is the one consumer that can't use eve's own session API.
Priority: a durable handle that outlives the parent turn, send() for further turns, readable status/progress, cancel. Identity continuity across the hop (#604) is what lets the worker's tools authorize as the right principal.
If #635 grows a session-shaped handle rather than a job-shaped one, this becomes a comment there instead — happy to consolidate.
Related: #635, #1084, #661, #604, #362.
What problem are you trying to solve?
I'm building a gateway/orchestrator agent on eve — a chat front door that never does the work itself. It classifies an ask, authorizes it, dispatches it to an execution backend, and relays progress back to the humans in the thread. Backends are heterogeneous: Cursor Cloud Agents today, other eve agents alongside them, more later.
Every backend has to satisfy one executor contract:
Cursor Cloud Agents satisfy all four.
defineRemoteAgentsatisfies onlylaunch— a remote call is one turn in, one result out, and no handle/id allows for follow-ups, so the other three verbs have nowhere to go.In the orchestrator code, I have a union whose second variant can't do three of the four verbs:
Everything downstream special-cases the second kind, including prose telling the model to complete the call itself because authored code can't.
Why this isn't the background-tasks story
#635 and #1084 give me detach and lifecycle — parent turn freed, status/cancel, completion notification. Both hit me too. Neither gives me a worker that stays a conversation: a task completes once, and I need to send turn 2 and turn 3 into the same worker with its context intact.
The distinguishing verb is
steer, and it's the one users exercise. From a live multiplayer thread:tasks/updateisn't that, and cancel-and-relaunch discards accumulated context while doubling cost and side effects.Proposed solution
A remote hop opens a durable session instead of consuming a turn:
That's roughly
POST /eve/v1/session/<id>plus the stream endpoint — machinery that already exists for external clients. The gap is thatdefineRemoteAgentdoesn't expose it to a calling agent, so agent-to-agent is the one consumer that can't use eve's own session API.Priority: a durable handle that outlives the parent turn,
send()for further turns, readable status/progress, cancel. Identity continuity across the hop (#604) is what lets the worker's tools authorize as the right principal.If #635 grows a session-shaped handle rather than a job-shaped one, this becomes a comment there instead — happy to consolidate.
Related: #635, #1084, #661, #604, #362.