packages/core/src/templates/default/.agents/skills/actions/SKILL.md
How to create and run agent-callable actions in actions/. Use when creating a new action, adding an API integration, implementing a complex agent operation, or running pnpm action commands.
npx skillsauth add BuilderIO/agent-native actionsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Complex operations the agent needs to perform are implemented as actions in actions/. The agent runs them via pnpm action <name>.
Actions give the agent callable tools with structured input/output. They keep the agent's chat context clean (no massive code blocks), they're reusable, and they can be tested independently.
Create actions/my-action.ts:
import fs from "fs";
import { parseArgs, loadEnv, fail, agentChat } from "@agent-native/core";
export default async function myAction(args: string[]) {
loadEnv();
const parsed = parseArgs(args);
const input = parsed.input;
if (!input) fail("--input is required");
const outputPath = parsed.output ?? "data/result.json";
const raw = fs.readFileSync(input, "utf-8");
const data = JSON.parse(raw) as unknown;
fs.writeFileSync(outputPath, JSON.stringify(data, null, 2));
agentChat.submit(`Processed ${input}, result saved to ${outputPath}`);
}
defineAction with Zod schema (recommended for new actions)import { z } from "zod";
import { defineAction } from "@agent-native/core";
export default defineAction({
description: "Process some data",
schema: z.object({
input: z.string().describe("Input file path"),
output: z.string().optional().describe("Output file path"),
}),
run: async (args) => {
// args is fully typed: { input: string; output?: string }
// do work
return "Done";
},
});
The schema field accepts a Zod schema (or any Standard Schema-compatible library). It provides runtime validation with clear error messages, TypeScript type inference for run() args, and auto-generated JSON Schema for the agent's tool definition. zod is a dependency of all templates.
The legacy parameters field (plain JSON Schema object) still works as a fallback.
pnpm action my-action --input data/source.json --output data/result.json
The default template uses core's runScript() in actions/run.ts:
import { runScript } from "@agent-native/core";
runScript();
This is the canonical approach for new apps. Action names must be lowercase with hyphens only (e.g., my-action).
defineAction with a Zod schema: for input validation. The framework validates automatically and returns clear error messages for invalid input. This prevents malicious or malformed input from reaching your code. The legacy parseArgs() format has no runtime validation — use it only for internal/dev scripts, not user-facing actions.db-exec/db-query tools which parameterize queries automatically (? placeholders). Drizzle ORM queries are always safe.loadEnv() if the action needs environment variables (API keys, etc.).fail() for user-friendly error messages (exits with message, no stack trace).agentChat.submit() to report results or errors back to the agent chat.@agent-native/core -- Don't redefine parseArgs() or other utilities locally.API integration action (e.g., image generation):
import fs from "fs";
import { parseArgs, loadEnv, fail } from "@agent-native/core";
export default async function generateImage(args: string[]) {
loadEnv();
const parsed = parseArgs(args);
const prompt = parsed.prompt;
if (!prompt) fail("--prompt is required");
const outputPath = parsed.output ?? "data/generated-image.png";
const imageUrl = await callImageAPI(prompt);
const buffer = await fetch(imageUrl).then((r) => r.arrayBuffer());
fs.writeFileSync(outputPath, Buffer.from(buffer));
}
Data processing action:
import fs from "fs";
import { parseArgs, fail } from "@agent-native/core";
export default async function transform(args: string[]) {
const parsed = parseArgs(args);
const source = parsed.source;
if (!source) fail("--source is required");
const data = JSON.parse(fs.readFileSync(source, "utf-8")) as unknown[];
const result = data.map(transformItem);
fs.writeFileSync(source, JSON.stringify(result, null, 2));
}
pnpm action foo-bar looks for actions/foo-bar.ts.--key value or --key=value format. Boolean flags use --flag (sets value to "true").pnpm action <name>tools
Public booking flow — the state machine, animations, and URL/app-state sync.
tools
Trigger-based automations — reminders, follow-ups, webhooks — across the booking lifecycle.
tools
Team event types, round-robin assignment, collective bookings, host weights, and no-show calibration.
development
The pure `computeAvailableSlots` function — inputs, outputs, invariants, and debugging guide.