#Call actions using their names
1 messages · Page 1 of 1 (latest)
Hi @trim jackal. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
Short answer: No — Convex is designed for you to call functions via the generated api/internal references, not by string names.
- Public and internal functions are exposed as typed endpoints through the generated api (and internal) objects; clients and server code call them via these references (for example, React’s useMutation/useAction with api functions, server ctx.runMutation with internal functions) (Calling mutations from clients, Calling actions from clients, Internal functions).
- This approach enforces validation, transaction semantics, access control (public vs internal), and end-to-end type safety. Calling functions “by name” is discouraged and considered an anti-pattern; the exports in /convex are API endpoints you invoke through the generated references, not arbitrary callables by string key (Discord: anti-pattern discussion, Discord: separation of exposure vs model).
- In tests, you likewise call them via t.query/t.mutation/t.action with api/internal references, not names (convex-test).
If you’re looking to avoid importing many individual functions, you can organize and re-export modules (e.g., barrel files) but you still call through api/internal, not by string name (Discord: code organization tip).
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@trim jackal Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@frank iron But i have saw in the code of an official convex package doing context.runAction("auth:...", ....)
Let me check the knowledge base for you again. One moment! :books:
You’re right that there are cases showing actions run “by name.” Two clarifications:
-
In the browser/client, BaseConvexClient.action(name, args) accepts a string name: this is the public client API to execute an action by its name (e.g., "module:function"). It returns a Promise of the action’s result (this is for clients, not server code) (BaseConvexClient.action).
-
On the server, inside an action, ctx.runAction exists and can call another action. However, best practice is to avoid runAction unless you’re crossing runtimes (Convex runtime -> Node.js runtime); otherwise extract shared code into a helper instead of nesting actions. Also, prefer calling internal functions via internal references rather than names for type-safety and security (GenericActionCtx methods, Use runAction only when using a different runtime, Only schedule and ctx.run* internal functions).
There’s also an advanced pattern in community content that builds a retrier which schedules actions by constructing a function reference from a string name (makeFunctionReference<"action">(name))—useful, but note the warnings about exposure and that it’s done via scheduler, not direct invocation (Retry actions: how it works).
So:
- Clients can call actions by name via the client API.
- Server code should prefer internal function references; use ctx.runAction sparingly, mainly for cross-runtime needs.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@trim jackal Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@frank iron can i use the function definition as a reference ?
Let me check the knowledge base for you again. One moment! :books:
Short answer: not directly. You should pass Convex function references (from the generated api/internal objects) or construct one explicitly, not the raw function definition.
- Use generated references: api.module.fn or internal.module.fn. These are FunctionReferences that tools like useQuery/ctx.runMutation/t.action accept (Generated api/internal, Internal functions: calling via internal).
- If you’re not using codegen, you can build a reference by name with makeFunctionReference("path/to/file:functionName") (makeFunctionReference, Query names format).
- Advanced/component APIs can also turn a FunctionReference into a serializable handle via createFunctionHandle, but this still starts from a FunctionReference, not a function definition (createFunctionHandle, FunctionHandle).
Calling the exported function directly is an anti-pattern because it bypasses argument validation and transactional/isolated execution; always invoke through the Convex function reference mechanisms (Discord discussion: anti-pattern).
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@trim jackal Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@frank iron the thing is that i don't use codegen because am building a reusable library and i don't have an exact path because again am building a library so ican't use the path or anyApi. How do i do ? how is createFunctionHandle used ?
Let me check the knowledge base for you again. One moment! :books:
If you’re not using codegen, you can still work with function references and handles without hardcoding paths:
-
Build a FunctionReference from a string name at runtime with makeFunctionReference. The name format is "dir/module:export" (e.g., "auth/login:perform"). This returns a typed FunctionReference you can pass to clients, ctx.run*, or schedulers (makeFunctionReference docs; query name format) (makeFunctionReference, Query names).
-
If you need a serializable handle (for components/scheduling across pushes), create one from a FunctionReference using createFunctionHandle, which yields a FunctionHandle you can store/pass around. Note this API is for Components and marked unstable (createFunctionHandle; FunctionHandle) (createFunctionHandle, FunctionHandle).
Example (no codegen, dynamic name):
import { makeFunctionReference } from "convex/server";
// Build a reference from a string assembled by your library
const ref = makeFunctionReference<"action">(runtimeNameString);
// Use with ctx.runAction / scheduler / clients, etc.
// e.g., inside an action:
// await ctx.runAction(ref, args);
If you have a FunctionReference and want its address parts, server utilities exist:
- getFunctionName(functionReference) gives "dir/module:export" (useful for logging or serialization) (getFunctionName).
- getFunctionAddress can expose handle/name/reference forms used by Components (advanced) (getFunctionAddress).
Notes:
- Clients can also call by string name if needed (same "dir/module:export" form) as used by Convex’s REST and proxy API generation patterns (In search of magic).
- Prefer internal functions and pass references/handles around rather than raw function definitions, for safety and type guarantees (Internal functions, Best practice: only ctx.run* internal).