بنقرة واحدة
automation-slice
builds an automation slice from an event model
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
builds an automation slice from an event model
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | automation-slice |
| description | builds an automation slice from an event model |
Make sure to read the Agents.md file before building anything.
If the processors-Array is not empty, it´s an automation slice.
Important - an automation slice is "just" a state-change slice with an additional automation that triggers the command. So also read the skill for 'state-change-slice'
restaurantId in their metadata (camelCase)locationId or location_id - these are outdated and forbiddenrestaurant_id column (snake_case)Automations are processes that happen in the background, based on a TODO List. TODO Lists are always tables (read models) and each row in the table is a TODO Item.
The automation is only responsible to:
┌─────────────────┐
│ TODO List │ (Read Model - Inbound Dependency)
│ "items to do" │ Example: "clerks_to_invite", "items_to_fetch"
└────────┬────────┘
│
│ reads
│
┌────────▼────────┐
│ processor.ts │ (CRON scheduled automation)
│ │ - Fetches TODO items
│ │ - Fires commands
└────────┬────────┘
│
│ invokes
│
┌────────▼────────┐
│ CommandHandler │ (State-change logic)
│ Command.ts │ - decide() function
│ routes.ts │ - evolve() function
└─────────────────┘
An automation slice consists of:
Two patterns exist in the codebase:
import {ProcessorConfig, ProcessorTodoItem, startProcessor} from "../../process/process";
import {handleYourCommand} from "./YourCommandCommand";
export type ItemToProcess = {
itemId: string,
// other fields from read model
}
const config: ProcessorConfig = {
schedule: "*/5 * * * * *", // Every 5 seconds (cron format)
endpoint: "your-todo-list-collection", // Read model endpoint
query: {
"status": "OPEN", // Filter criteria
"_limit": "1" // Process one at a time
}
}
const handler = async (item: ItemToProcess & ProcessorTodoItem) => {
console.log(`Processing item: ${item.itemId}`)
try {
await handleYourCommand(`aggregate-${item.itemId}`, {
type: "YourCommand",
data: {
itemId: item.itemId,
// map other fields
},
metadata: {}
})
console.log(`Successfully processed item: ${item.itemId}`)
} catch (error) {
console.error(`Error processing item ${item.itemId}:`, error)
}
}
export const processor = {
start: () => {
console.log("[YourProcessor] Starting processor...")
startProcessor<ItemToProcess>(config, handler)
}
}
import {ProcessorConfig} from "../../process/process";
import {YourCommand, handleYourCommand} from "./YourCommandCommand";
import cron from "node-cron";
import {createServiceClient} from "../../supabase/api";
const config: ProcessorConfig = {
schedule: '*/30 * * * * *', // Every 30 seconds
endpoint: "your_todo_table", // Supabase table name
}
export const processor = {
start: () => {
cron.schedule(config.schedule, async () => {
console.log("Running process")
let client = createServiceClient()
let result = await client.from(config.endpoint).select("*")
if (result.count == 0) {
console.log(`Nothing to do for ${config.endpoint}`)
return;
}
for (const item of result.data ?? []) {
const command: YourCommand = {
type: "YourCommand",
data: {
itemId: item.itemId!
},
metadata: {}
}
const id = item.itemId
if (!id) {
throw `Cannot process Command ${command.type}. No Id available.`
}
await handleYourCommand(id, command)
}
})
}
}
┌───────────── second (0-59)
│ ┌─────────── minute (0-59)
│ │ ┌───────── hour (0-23)
│ │ │ ┌─────── day of month (1-31)
│ │ │ │ ┌───── month (1-12)
│ │ │ │ │ ┌─── day of week (0-7)
│ │ │ │ │ │
* * * * * *
Common schedules:
*/5 * * * * * - Every 5 seconds*/30 * * * * * - Every 30 seconds0 */1 * * * * - Every minute0 0 * * * * - Every hourTODO List Read Model: clerks_to_invite table
Automation: src/slices/ConfirmInvitation/processor.ts
Command: ConfirmInvitationCommand
Event Emitted: ClerkInvitationConfirmed
// processor.ts
const config: ProcessorConfig = {
schedule: '*/30 * * * * *',
endpoint: "clerks_to_invite",
}
// Fetches clerks from TODO list and confirms their invitations
for (const clerk of result.data ?? []) {
const command: ConfirmInvitationCommand = {
type: "ConfirmInvitation",
data: {
clerkId: clerk.clerkId!
},
metadata: {}
}
await handleConfirmInvitation(clerk.clerkId, command)
}
in each slice folder, generate a file .slice.json
{
"id" : "<slice id>",
"slice": "<slice title>",
"context": "<contextx>",
"link": "https://miro.com/app/board/<board-id>=/?moveToWidget=<slice id>"
}
<things>_to_<action> (e.g., clerks_to_invite, items_to_fetch)/api/query/<name>-collection endpointstatus field ("OPEN", "PROCESSING", "DONE")_limit: "1" to process one item at a time, preventing concurrent issuescatalogue-${itemId})[Command]Command.ts with decide/evolve functionsroutes.ts for HTTP API endpointSample input: read 'templates/sample-input.json'
The input defines: