Client method surface rules. Use when wiring browser/client code to actions, application state, framework routes, app APIs, uploads, auth, or settings.
73
92%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Browser/client code imports named methods, hooks, or client modules instead of hand-writing REST calls to framework or app routes.
Route shapes are transport details. If components and docs call
fetch("/_agent-native/...") or template /api/* routes directly, every caller
has to rediscover auth, base paths, request-source headers, JSON parsing, error
handling, optimistic updates, sync invalidation, and route quirks. A named client
method gives the UI, docs, and future agents one stable contract.
Look for an existing client API first.
| Need | Use |
|---|---|
| App action reads/writes | useActionQuery / useActionMutation from @agent-native/core/client/hooks |
| Imperative action calls | callAction from @agent-native/core/client/hooks |
| Browser application state | readClientAppState, writeClientAppState, setClientAppState, deleteClientAppState from @agent-native/core/client/hooks |
| Navigation/app-state sync | useAgentRouteState / useSemanticNavigationState from @agent-native/core/client/navigation |
| Agent chat context | Agent chat helpers from @agent-native/core/client/agent-chat |
| Ask the user a multiple-choice question from app code | askUserQuestion from @agent-native/core/client/agent-chat (renders inline in the agent panel; answer goes to the agent — do not build a custom modal) |
| Live sync | useDbSync, useChangeVersion, useChangeVersions from @agent-native/core/client/hooks |
| Extension iframe calls | appAction, appFetch, extensionFetch from the extension runtime |
Action fetch behavior: every useActionQuery / useActionMutation /
callAction request is bounded by a 60s timeout, and timeouts surface as
errors instead of retrying silently. useActionQuery cancels superseded
requests automatically via React Query's abort signal. For imperative
calls, callAction(name, params, { method, signal, timeoutMs }) accepts an
AbortSignal and a timeoutMs override for legitimately long operations.
If no client API exists, add the narrowest helper at the boundary.
packages/core/src/client/*.templates/<app>/app/hooks/*,
templates/<app>/app/lib/*, or an existing local client module.@agent-native/core/client/*
entry for their domain. Never recommend the deprecated broad
@agent-native/core/client barrel in new code.fetch, agentNativePath, and route paths inside that helper,
not scattered through components or docs.Teach the helper, not the route.
Docs, skills, examples, and generated code should show:
await setClientAppState("selection", selection, { keepalive: true });not:
await fetch("/_agent-native/application-state/selection", {
method: "PUT",
body: JSON.stringify(selection),
});Raw route calls are acceptable only inside low-level client helpers or for route-shaped protocols that cannot be hidden cleanly:
appFetch / extensionFetch, which are themselves exposed
client methodsEven for exceptions, prefer a named helper as soon as more than one caller needs the behavior.
fetch("/_agent-native/..."), fetch(agentNativePath(...)), or
template /api/* calls directly in React components for normal app data,
actions, settings, or application state./api/* routes just to make client fetches look
simpler; expose an action and call it with action hooks.actions — app operations shared by UI and agent.context-awareness — application-state navigation and selection helpers.real-time-sync — keeping helper-backed UI reads fresh.server-plugins — when a new route is actually warranted.references/legacy-client-fetch-audit-2026-06-03.md — known legacy cleanup
targets found when this rule was added.c1ee18b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.