Calling Actions
Run actions and read their output — the same on any side of the connection.
Once your runtime is set up, calling an action looks the same on any side — client or server — and it doesn’t matter whether the action runs right here or over on a peer. You call it the same way either way.
Just get the result
Section titled “Just get the result”The everyday case: run the action and get its output back. It throws if the action fails — whether that’s a declared error or a connection problem.
const output = await act_user.action.getUser .request({ userId: "u_123" }) .runToOutput();
console.log(output); // { id: "u_123", name: "Alice" }Keep a handle on the running call
Section titled “Keep a handle on the running call”If you want to track progress or be able to cancel, hold onto the RunningAction and wait for its full result:
const running = await act_user.runAction( act_user.action.getUser.request({ userId: "u_123" }),);
const result = await running.waitForResultPayload();console.log(result.output);Handling errors where you call
Section titled “Handling errors where you call”Any error you listed with .throws(domain, ids?) comes back fully typed. Use castNiceError and the domain’s checks to narrow down which one it is:
import { castNiceError } from "@nice-code/error";
try { const output = await act_user.action.getUser.request({ userId }).runToOutput();} catch (e) { const error = castNiceError(e); if (err_user.isExact(error) && error.hasId("not_found")) { console.log("User not found:", error.getContext("not_found").userId); }}This request(...).runToOutput() shape is the same whether the action runs locally (a handler in this runtime) or remotely (over a connection to a peer) — the runtime figures out where it needs to go.
Getting a result back instead of a throw
Section titled “Getting a result back instead of a throw”runToResult() hands you the outcome as a value instead of throwing. You check expected (did this action
say it could throw this error?) rather than wrapping every call in try/catch:
const result = await act_user.action.getUser.request({ userId }).runToResult();if (result.ok) use(result.output);else if (result.expected) handleDeclared(result.error);else report(result.error); // an error this action didn't declare, or an unexpected crashThis is the recommended path — see Error Handling → for the full model
(expected vs isUnhandled, the typed isExpectedError guard, and how it surfaces in devtools).
Actions defined with
.reliable()call exactly the same way — the only differences are when the promise settles (it retries across reconnects instead of failing fast) and an optional per-callstreamKeyon.run()/.runToOutput()to keep independent streams (one per room, per entity) separately ordered.