# How to Define a New Action in Agent-Native Using `defineAction`

> Learn to define a new action in Agent Native using defineAction. Import it, create a Zod schema for validation, implement your business logic with an async run function, and export the default.

- Repository: [Builder.io/agent-native](https://github.com/BuilderIO/agent-native)
- Tags: how-to-guide
- Published: 2026-06-28

---

**To define a new action in Agent-Native, import `defineAction` from `@agent-native/core`, provide a Zod schema for input validation, implement an async `run` function containing your business logic, and export the result as the default export.**

In the BuilderIO/agent-native framework, every piece of business logic is encapsulated as a shared action. This architecture ensures that whether you are building a UI component, an agent tool, or a CLI command, you invoke the same canonical implementation. Defining a new action requires only a single file that registers itself with the framework at build time.

## Architecture Overview

Agent-Native treats actions as the central source of truth for all work. When you use `defineAction`, you create a contract that specifies exactly what data the action expects and how it executes.

- **Schema Validation**: You supply a Zod schema (`schema: z.object({...})`) that guarantees the shape of input arguments. The framework validates the payload before the `run` handler executes.
- **Run Implementation**: The `run` function receives the **parsed** arguments and an execution context containing helpers like database connections or auth utilities.
- **Client Usage**: All clients call the same exported action via `useActionMutation` or `useActionQuery` (frontend) or `appAction` (backend). No separate REST endpoint is required.
- **Observability**: The core runtime in [`packages/core/src/action.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/action.ts) automatically wraps every action with telemetry, permission checks, and error handling.

## Creating Your First Action

### Importing the Core Utility

Begin by importing `defineAction` from the core package. This utility is the primary entry point for registering actions with the Nitro server and client-side registry.

```typescript
import { defineAction } from "@agent-native/core";
import { z } from "zod";

```

### Defining the Input Schema

Provide a Zod schema that describes the expected input fields. This schema acts as a runtime validator, preventing malformed data from reaching your business logic.

```typescript
const schema = z.object({
  userId: z.string(),
  userEmail: z.string().email(),
  welcomeMessage: z.string().optional(),
});

```

### Implementing the Run Handler

Write the `run` function to execute the actual work, such as database writes or external API calls. This function receives the validated arguments and the execution context.

```typescript
run: async ({ userId, userEmail, welcomeMessage }) => {
  await db.insert(welcomeEmails).values({
    userId,
    email: userEmail,
    message: welcomeMessage ?? "Welcome!",
  });
  
  return { success: true };
}

```

### Exporting for Registration

Export the result of `defineAction` as the default export so the framework can discover it automatically. The action is registered at build time and published to the shared action registry.

## Complete Code Example

Here is a minimal skeleton that demonstrates the full pattern used across the repository:

```typescript
import { defineAction } from "@agent-native/core";
import { z } from "zod";

export default defineAction({
  description: "Create a welcome email for a new user",

  schema: z.object({
    userId: z.string(),
    userEmail: z.string().email(),
    welcomeMessage: z.string().optional(),
  }),

  run: async ({ userId, userEmail, welcomeMessage }) => {
    await db.insert(welcomeEmails).values({
      userId,
      email: userEmail,
      message: welcomeMessage ?? "Welcome!",
    });

    return { success: true };
  },
});

```

*Real-world reference:* See the `create-workflow` action in [`packages/scheduling/src/actions/create-workflow.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/scheduling/src/actions/create-workflow.ts) for a complex implementation involving database transactions and conditional logic.

## Consuming the Action

Once defined, the action becomes instantly available throughout the entire application under an auto-generated name based on the file path.

### From React Components

Use the `useActionMutation` hook from `@agent-native/react` to invoke the action from the frontend. The framework handles loading states, caching, and error boundaries automatically.

```tsx
import { useActionMutation } from "@agent-native/react";

const sendWelcome = useActionMutation("welcomeEmail.create");

function SendButton() {
  const { mutate, isLoading } = sendWelcome;

  const handleClick = () => {
    mutate({
      userId: "123",
      userEmail: "joe@example.com",
      welcomeMessage: "Hey Joe, glad you're here!",
    });
  };

  return <button onClick={handleClick} disabled={isLoading}>Send</button>;
}

```

### From Agent Tools or API Routes

On the server side, use the `appAction` helper to invoke the action from agent tools, API routes, or the CLI.

```typescript
import { appAction } from "@agent-native/core";

await appAction("welcomeEmail.create", {
  userId: ctx.user.id,
  userEmail: ctx.user.email,
});

```

All calls route through the same `run` implementation, guaranteeing identical behavior and validation rules across every layer of the stack.

## Key Source Files and References

- **[`packages/core/src/action.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/action.ts)**: Contains the core implementation of `defineAction` and the runtime registration logic.
- **[`packages/scheduling/src/actions/create-workflow.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/scheduling/src/actions/create-workflow.ts)**: Provides a production-ready example of a complex action with schema validation and database operations.
- **[`templates/videos/actions/view-screen.ts`](https://github.com/BuilderIO/agent-native/blob/main/templates/videos/actions/view-screen.ts)**: Offers a template-based starter file you can copy for new actions.

## Summary

- **Import** `defineAction` from `@agent-native/core` to create a new action.
- **Define** a Zod schema to validate inputs before execution.
- **Implement** an async `run` function containing your business logic.
- **Export** the result as the default export to register it with the framework.
- **Invoke** the action from any client using `useActionMutation` (frontend) or `appAction` (backend).

## Frequently Asked Questions

### What is the purpose of the Zod schema in `defineAction`?

The Zod schema acts as a runtime contract that validates the shape of incoming arguments. If the payload fails validation, the framework rejects the request before your `run` function executes, ensuring type safety and preventing malformed data from reaching your database or external APIs.

### Can I access the database or authentication context inside the `run` function?

Yes. The `run` function receives a context object as its second argument containing execution helpers like database connections, authentication state, and other framework utilities. This allows you to perform secure operations without manual context passing.

### How does the framework generate the action name?

The action name is auto-generated based on the file path relative to the actions directory. For example, a file at [`actions/welcomeEmail/create.ts`](https://github.com/BuilderIO/agent-native/blob/main/actions/welcomeEmail/create.ts) becomes accessible as `"welcomeEmail.create"` in `useActionMutation` and `appAction` calls.

### Where should I place new action files in the project?

Place new action files inside the `actions/` directory of the relevant package or template. The build system scans these directories, automatically imports files that export a `defineAction` result as default, and registers them with the shared action surface.