Getting Started
The easiest way to set up automations is to describe what you want in plain language. Here are some prompts you can try:Your First Automation
Here’s the simplest possible automation — it logs a message every time a label is added to a session:~/.craft-agent/workspaces/{workspaceId}/automations.json and it starts working immediately — no restart needed.
Scheduling a Prompt
Want Craft Agent to do something for you on a schedule? Use a prompt action with a cron expression:How Automations Work
When an event fires (e.g., a label is added, a tool runs, or a cron schedule matches), Craft Agent checks your configuration for matching entries and executes them. There are two types of actions:- Command actions — execute shell commands with event data available as environment variables
- Prompt actions — send a prompt to Craft Agent, creating a new session (App events only)
Configuration File
Automations are configured per-workspace inautomations.json:
Basic Structure
Managing Automations
In the UI
Automations are listed in the sidebar under Automations. From here you can:- Enable / Disable — Toggle individual automations on or off without removing them
- Duplicate — Create a copy of an existing automation with a “Copy” suffix
- Delete — Remove an automation permanently
- Test — Manually trigger an automation to verify it works before waiting for the real event. The test runner resolves
@mentions, enables sources, and uses the configuredllmConnection/model— the same code path as the scheduler. - Execution history — Each automation records success and failure to a timeline, viewable in the detail page. History is stored in
automations-history.jsonland retained to the last 20 runs per automation (max 1000 entries total).
In the Config File
You can also manage automations by editingautomations.json directly. Changes take effect immediately — no restart required.
Enabling and disabling: Set "enabled": false on any matcher to temporarily disable it without removing the configuration. Omit the field or set it to true to re-enable.
automations.json. If an event type has no remaining matchers, you can remove the entire event key.
Events
App Events
Triggered by Craft Agent itself. Support both command and prompt actions.Renamed:
TodoStateChange was renamed to SessionStatusChange. The old name still works as a deprecated alias but will show a validation warning. Update your automations to use SessionStatusChange.Agent Events
Passed to the Claude SDK. Only command actions are supported (no prompt actions).Action Types
Command Actions
Execute a shell command when the event fires. Event data is available through environment variables.Prompt Actions
Send a prompt to Craft Agent, creating a new session. Only works with App events.
Features:
- Use
@mentionsto reference sources or skills (e.g.,@github,@linear) - Environment variables are expanded (e.g.,
$CRAFT_LABEL,${CRAFT_SESSION_NAME}) - Mentioned sources are automatically activated for the new session
llmConnection value is the slug of an LLM connection configured in AI Settings. The model value is a model ID supported by the provider. If either is invalid or not found, it gracefully falls back to the workspace default.
Thinking level resolution: thinkingLevel on the action takes precedence; if omitted, the workspace default applies; if neither is set, sessions default to "medium". The legacy "think" value from older configs is silently migrated to "medium". Backends gracefully cap unsupported values (e.g. Anthropic auto-degrades xhigh → high on models that don’t support it; Pi caps max at xhigh).
Matchers
Regex Matching
Most events use regex matching against the event’s match value:matcher field to match all events of that type.
Examples:
Cron Matching
ForSchedulerTick events, use cron expressions instead of regex:
minute hour day-of-month month day-of-week
Common patterns:
Timezone: Uses IANA timezone names (e.g.,
Europe/Budapest, America/New_York). Defaults to system timezone if not specified. Verify with crontab.guru.
Conditions
Conditions are optional filters that run after the matcher/cron matches but before actions fire. All conditions in the array must pass (implicit AND). If the array is empty or omitted, actions fire unconditionally.Time Conditions
Check time-of-day and day-of-week in a given timezone.Overnight ranges: If
after is later than before (e.g., "after": "22:00", "before": "06:00"), the range wraps across midnight.State Conditions
Check fields from the event payload. Useful for filtering on specific transitions or values.Transition fields: For
permissionMode and sessionStatus, from/to automatically resolve to the correct payload keys (oldMode/newMode, oldState/newState).Logical Composition
Combine conditions withand, or, and not:
Matcher Options
Each matcher entry supports these optional fields:Telegram Topic Routing
When you have a Telegram supergroup paired in Settings → Messaging → Telegram, you can route the sessions a matcher spawns into a dedicated forum topic by setting thetelegramTopic field.
telegramTopic value) post into the same topic.
Activation requirements
All of these must hold; otherwise the field is silently ignored and the session runs without a Telegram binding (same as if the field were absent):- A Telegram supergroup is paired at Settings → Messaging → Telegram
- The Telegram bot is connected
- The bot has the Manage Topics admin permission in the supergroup
Setting up the Telegram supergroup
If you haven’t paired a supergroup yet, follow these steps. The whole flow takes about a minute.1. Create a supergroup with topics enabled
A regular Telegram group can’t host topics — you need a supergroup with “Topics” mode enabled.- New group: Telegram → New Group → add anyone (or yourself for a solo workspace) → set a name. Telegram converts groups to supergroups automatically once members exceed a threshold or you flip Topics on.
- Enable Topics: Open the group → tap the group name → Edit (pencil icon on mobile, ⋯ on desktop) → toggle Topics on → Save. The group is now a forum supergroup; you’ll see a “General” topic and a ”+” button to create more.
2. Add the bot to the supergroup
Open the supergroup → tap the group name → Add members → search for your bot’s username (e.g.@CraftAgentsBot) → add it.
3. Make the bot an admin with “Manage Topics”
This is the step most people miss — the bot needs explicit permission to create new topics, otherwise topic-creation calls return400: Bad Request: not enough rights to create a topic.
- In the supergroup, tap the group name → Edit → Administrators.
- Tap Add Administrator → pick the bot.
- In the permissions list, toggle on Manage Topics (other permissions like Delete Messages or Pin Messages are optional and not required by the topic-routing feature).
- Tap Save / Done.
4. Pair the supergroup with the workspace
- In the Craft Agent app: Settings → Messaging → Telegram → Pair Supergroup.
- The dialog shows a 6-digit code, a deep link to the bot, and a 5-minute countdown.
- In Telegram, in any topic of your supergroup, type
/pair <code>(replace<code>with the digits from the dialog). - The bot replies with a confirmation. The dialog closes automatically and the Settings row updates with the supergroup’s title and chat ID.
telegramTopic set will now create topics in
this supergroup.
Notes
- Topic names are 1–128 characters and case-sensitive (
"Reports"and"reports"are different topics). - Two matchers using the same
telegramTopicvalue share one topic — useful for grouping related automations. - If you change a matcher’s
telegramTopicvalue, the next run uses (or creates) the new topic; the old topic remains in Telegram with its history intact. - Renaming the topic in Telegram doesn’t sync back — the binding follows the topic ID, not the display name.
Environment Variables
Common Variables
Available to all command actions:App Event Variables
Dynamically generated from event payloads: Label events (LabelAdd, LabelRemove):
CRAFT_LABEL— Label ID being added/removed
CRAFT_OLD_MODE— Previous permission modeCRAFT_NEW_MODE— New permission mode
CRAFT_IS_FLAGGED—trueorfalse
CRAFT_OLD_STATE— Previous session statusCRAFT_NEW_STATE— New session status
CRAFT_LOCAL_TIME— Current time (HH:MM)CRAFT_LOCAL_DATE— Current date (YYYY-MM-DD)
Agent Event Variables
Tool events (PreToolUse, PostToolUse, PostToolUseFailure):
CRAFT_TOOL_NAME— Tool being usedCRAFT_TOOL_INPUT— Tool parameters as JSONCRAFT_TOOL_RESPONSE— Tool output (PostToolUse only)CRAFT_ERROR— Error message (PostToolUseFailure only)
SessionStart):
CRAFT_SOURCE— Session source (e.g.,startup,resume)CRAFT_MODEL— Model name
SubagentStart, SubagentStop):
CRAFT_AGENT_ID— Subagent IDCRAFT_AGENT_TYPE— Subagent type
Permission Modes
Command actions run with security checks by default. You can adjust this per matcher:Labels for Prompt Actions
Prompt actions can attach labels to the sessions they create. This makes it easy to filter and organise scheduled sessions:"priority::${CRAFT_LABEL}".
Rate Limits
To prevent runaway loops (e.g., an automation that indirectly triggers itself), the event bus enforces rate limits:
Excess events are silently dropped for the remainder of the 60-second window.
Examples
Daily Morning Briefing
Schedule a prompt every weekday at 9 AM:Weekday-Only AI News (with Conditions)
Use atime condition to restrict a daily schedule to weekdays:
Permission Mode Gate (with Conditions)
Only notify when permission mode changes specifically fromsafe to allow-all:
Log Label Changes
Track when labels are added or removed:macOS Notification on Urgent Label
Audit Permission Mode Changes
Multiple Schedules with Enable/Disable
Run different automations at different times, and disable some without deleting:"enabled" is set to true or removed.
Prompt with Custom Connection, Model, and Thinking Level
Override provider, model, and thinking level for a specific automation:Validation
Ask Craft Agent to validate your automations:config_validate tool with target: "all".
The validator checks for:
- Invalid JSON syntax
- Unknown event names
- Empty actions arrays
- Invalid cron expressions or timezones
- Invalid or unsafe regex patterns (ReDoS prevention)
- References to non-existent labels
- Invalid condition types, field names, or weekday values
- Condition nesting depth exceeding limits
- Missing
llmConnectionslugs (error — will fail at runtime) - Model/provider mismatches when both
llmConnectionandmodelare specified (warning) - Invalid
thinkingLevelvalues (legacy"think"is silently migrated to"medium")
Security
Automations include several built-in safety measures:- Shell injection prevention — User-controlled values in environment variables (session names, labels, prompts) are automatically escaped
- ReDoS protection — Regex patterns are limited to 500 characters and checked for catastrophic backtracking patterns
- Rate limiting — Prevents infinite loops from automations that trigger other automations
- Permission modes — Commands are checked against an allowlist by default
- Timeouts — Commands are killed after their timeout expires (with SIGKILL fallback)
Best Practices
Best Practices
- Start simple — Test with
echocommands before writing complex scripts - Use labels — Tag scheduled sessions for easy filtering
- Set timeouts — Prevent runaway commands with the
timeoutfield - Log failures — Redirect stderr to track issues:
command 2>> ~/automation-errors.log - Be specific — Use matchers to avoid triggering on every event
- Test cron — Use crontab.guru to verify expressions
- Use
enabled: false— Temporarily disable automations instead of deleting them during debugging
Troubleshooting: Automation not firing
Troubleshooting: Automation not firing
- Check event name — Must be exact (e.g.,
LabelAddnotlabeladd) - Check matcher — Regex must match the event’s match value
- Check cron — For SchedulerTick, verify your cron expression
- Check enabled — Ensure the matcher doesn’t have
"enabled": false - Check logs — Look for
[automations]in the application logs
Troubleshooting: Command blocked
Troubleshooting: Command blocked
If you see “Bash command blocked” errors:
- Add
"permissionMode": "allow-all"to the matcher - Or simplify the command to avoid shell constructs like
$()
Troubleshooting: Prompt not creating session
Troubleshooting: Prompt not creating session
- Ensure the event is an App event (prompt actions don’t work with Agent events)
- Check that the prompt text is not empty
- Verify
@mentionsreference valid sources or skills
Troubleshooting: Condition not matching
Troubleshooting: Condition not matching
- Check weekday spelling — Must be 3-letter lowercase:
mon,tue,wed,thu,fri,sat,sun - Check timezone — Use IANA names (e.g.,
Europe/Budapest). Invalid timezones silently fall back to system local - Check time format — Must be
HH:MMin 24-hour format (e.g.,09:00, not9:00 AM) - Check state field names — Use
permissionMode,sessionStatus,labels,isFlagged - Check nesting depth — Conditions nested deeper than 8 levels always evaluate to false
- Check logs — Look for
[automations]entries that mention condition evaluation