Problem
Today Remo capability calls are request/response only. In some app flows, a capability can start work but the app is not actually ready for the next capability when the response returns.
A common example is login:
auth.login succeeds and returns
- the app continues doing follow-up work in the background
- after some delay, the home screen reload finishes
- only then is the app ready for the next capability call
Right now the client has to guess with fixed sleeps or separate ad hoc polling. That is fragile and makes capability-driven flows less reliable.
Proposed Solution
Add first-class support for app-defined custom events, then add a client flow that can invoke a capability and wait for a matching event before considering the overall operation complete.
The important scope here is not a full multi-step workflow DSL. The core primitive is:
- call a capability
- let the app continue asynchronous follow-up work
- emit a custom event when the app is actually ready
- let the client wait for that event with timeout/failure handling
Example:
remo call -a <addr> auth.login '{"username":"demo","password":"demo"}' \
--await-event homepage.reloaded \
--timeout 30s
On the app side, Remo would need a public SDK API to emit custom events, not just built-in lifecycle events like capabilities_changed.
A more robust version should support correlation IDs so the awaited event can be tied to the specific capability invocation, for example:
- client includes a correlation ID with
auth.login
- app emits
homepage.reloaded with the same correlation ID
- Remo waits for the matching event, not any event with that name
Potential pieces:
- SDK API to emit custom events from Swift/ObjC
- CLI support for
call plus await event
- timeout support
- clear failure modes when the event never arrives
- optional payload filtering
- correlation ID support
Alternatives Considered
-
Keep capability handlers open until all downstream work finishes.
This makes the initial capability response mean both "accepted" and "fully ready", which is less expressive and may force long-running handlers to stay open unnecessarily.
-
Use fixed sleeps between capability calls.
This is simple but unreliable and app-specific.
-
Add a full workflow/compound-capability DSL.
This seems heavier than necessary right now. The smaller primitive of call + await matching event likely solves the immediate problem with less API surface.
Additional Context
This fits the existing protocol shape well because Remo already has unsolicited events and remo watch. What seems missing is a public app-side way to emit custom events plus a higher-level client flow to wait for a specific event after invoking a capability.
Example target flow:
- call
auth.login
- receive immediate success response
- app continues post-login sync/navigation/reload work
- app emits
homepage.reloaded
- only then does Remo report the whole operation as complete
If helpful, expected acceptance criteria could be:
- app code can emit named custom Remo events with JSON payload
remo call can optionally wait for a named event before exiting
- waiting supports timeout
- matching can use event kind plus optional payload fields
- correlation is supported to avoid races with unrelated events
Problem
Today Remo capability calls are request/response only. In some app flows, a capability can start work but the app is not actually ready for the next capability when the response returns.
A common example is login:
auth.loginsucceeds and returnsRight now the client has to guess with fixed sleeps or separate ad hoc polling. That is fragile and makes capability-driven flows less reliable.
Proposed Solution
Add first-class support for app-defined custom events, then add a client flow that can invoke a capability and wait for a matching event before considering the overall operation complete.
The important scope here is not a full multi-step workflow DSL. The core primitive is:
Example:
On the app side, Remo would need a public SDK API to emit custom events, not just built-in lifecycle events like
capabilities_changed.A more robust version should support correlation IDs so the awaited event can be tied to the specific capability invocation, for example:
auth.loginhomepage.reloadedwith the same correlation IDPotential pieces:
callplusawait eventAlternatives Considered
Keep capability handlers open until all downstream work finishes.
This makes the initial capability response mean both "accepted" and "fully ready", which is less expressive and may force long-running handlers to stay open unnecessarily.
Use fixed sleeps between capability calls.
This is simple but unreliable and app-specific.
Add a full workflow/compound-capability DSL.
This seems heavier than necessary right now. The smaller primitive of
call + await matching eventlikely solves the immediate problem with less API surface.Additional Context
This fits the existing protocol shape well because Remo already has unsolicited events and
remo watch. What seems missing is a public app-side way to emit custom events plus a higher-level client flow to wait for a specific event after invoking a capability.Example target flow:
auth.loginhomepage.reloadedIf helpful, expected acceptance criteria could be:
remo callcan optionally wait for a named event before exiting