Skip to content

Configuration: automation ​

The settings in agentx.json that make agents work on their own: scheduled jobs, services, incoming webhooks, workflows, learned procedures, notifications, approvals, resuming after a restart and due reminders. For the other sections and how to edit the file, see the Configuration reference.

"Default" is the value used when the key is left out. "required" means the entry is rejected without it; "—" means it is unset unless you set it.

crons ​

Scheduled jobs (also called routines), keyed by job id: crons.<id>. Each job either asks an agent to run a prompt or runs a shell command.

KeyTypeDefaultWhat it does
enabledbooleantrueTurns the job on or off without deleting it.
schedulestringrequiredWhen the job runs, as a cron expression such as 0 7 * * 1.
timezonestring"UTC"The timezone the schedule is read in, for example Europe/Paris.
agentstringrequiredThe agent that runs the prompt. For a command job, the agent told when it fails.
promptstring""What the agent is asked to do. A job needs a prompt or a command.
commandstring—A shell command run directly instead of an agent: no model, no tokens.
timeoutnumber600Time limit in seconds. Agent jobs get at least 2 hours; see time limits.
modelstring—Model for this job only, instead of the agent's model.
maxOutputTokensnumber (50–8000)—Asks the agent to keep its answer under about this many tokens. A soft cap added to the prompt.
autonomy"report" | "propose" | "act"— (acts as act)How much the run may do. See routine autonomy. Not allowed on command jobs.
onError"log" | "notify" | "disable", or a list of them"log"What happens when a run fails: log it, send a message, or turn the job off after 3 failures in a row. From the second failure in a row a message is sent anyway.
notifyobject—Where this job's messages go.
notify.channelstringrequiredChannel for the job's messages, for example telegram.
notify.chatIdstringrequiredThe chat on that channel.
notify.accountIdstring—Which account on that channel, when you have more than one.
fireTokenstring—Secret that lets another system start the job now. See fire a routine.
createdBystring—The agent that created the job from chat. Set by AgentX; an agent may only manage jobs it created, unless it is an admin.
approvalobject—A change an agent asked for that waits for you. Set by AgentX; cleared by agentx schedule approve or agentx schedule reject.
approval.action"create" | "delete"requiredWhat the agent asked for. A job waiting on create never runs.
approval.requestedBystringrequiredThe agent that asked.
approval.requestedAtstringrequiredWhen it asked (date and time).
json
"crons": {
  "weekly-summary": {
    "schedule": "0 8 * * 1",
    "timezone": "UTC",
    "agent": "writer",
    "prompt": "Summarise last week's merged changes",
    "onError": ["notify", "disable"],
    "notify": { "channel": "telegram", "chatId": "123456789" }
  }
}

services ​

Services answer a known kind of message with a fixed prompt, keyed by service id: services.<id>. When an incoming message matches a trigger, the service's prompt is sent to its agent.

KeyTypeDefaultWhat it does
namestringrequiredName shown in lists and logs.
triggerslist of objectsrequiredPatterns that start the service.
patternstringrequiredA trigger's regular expression, matched against the message text, ignoring case.
channelstring—Limits a trigger to one channel, for example whatsapp.
allowedContactslist of strings—Only these senders can start the service. Unset: anyone.
agentstringrequiredThe agent that runs the prompt.
promptstringrequiredThe prompt sent to the agent when a trigger matches.
schedulestring—A cron expression kept with the service. The daemon does not run services on a schedule yet; use crons for timed work.
timezonestring"UTC"Timezone for schedule.
notifyobject—A destination kept with the service (channel, chatId, notify.accountId). Not used by the daemon yet.

webhooks ​

The list of incoming webhooks, as managed on the dashboard's Webhooks tab. The address a system posts to is always /webhook/<agentId>/<source> on the daemon.

KeyTypeDefaultWhat it does
idstringrequiredShort name for the entry: lowercase letters, digits, - and _.
sourcestringrequiredThe sending system, for example github, gitlab or stripe.
agentIdstringrequiredThe agent that handles the event.
secretEnvstring—Name of the environment variable that holds the signing secret. When set, unsigned or wrongly signed requests are refused.
descriptionstring—A note for people reading the list.
enabledbooleantrueA disabled entry is ignored.
nodestring—Sends the event to this mesh peer instead of running it on this machine.
triggersmap of strings—Starts a different workflow per event type. Keys are event types such as issues.opened or Merge Request Hook; values are workflow ids.
defaultWorkflowstring—Workflow started when no triggers key matches. Unset: the agent handles the event itself.
json
"webhooks": [
  { "id": "repo-events", "source": "github", "agentId": "reviewer", "secretEnv": "GITHUB_WEBHOOK_SECRET",
    "triggers": { "pull_request.opened": "review-pr" } }
]

workflows ​

The workflow engine. See Workflows.

KeyTypeDefaultWhat it does
workflows.enabledbooleanfalseTurns the workflow engine on.
workflows.dirstring".agentx/workflows"Folder that holds workflow definitions.
workflows.n8nobject{"baseUrl":"","apiKey":""}Connects your n8n instance so the builder can list its workflows as steps.
workflows.n8n.baseUrlstring""Address of your n8n instance. Empty: not connected.
workflows.n8n.apiKeystring""n8n API key. Use an environment reference such as ${N8N_API_KEY}.
workflows.matchingobject{}Matching incoming messages to a workflow.
workflows.matching.enabledbooleanfalseChecks each message for a matching workflow.
workflows.matching.mode"suggest" | "auto""suggest"suggest only logs a match; auto runs the workflow instead of the agent.
workflows.matching.autoRunThresholdnumber (0–1)0.85In auto mode, how confident a match must be to run the workflow.
workflows.matching.suggestThresholdnumber (0–1)0.65How confident a match must be to count at all.
workflows.editor"disabled" | "readonly" | "edit""edit"The dashboard's workflow editor: hidden, view only, or editable.

procedures ​

Procedures are step-by-step guides AgentX learns from work that repeats. When the extraction job runs is set by the procedure-extract entry in crons, which agentx procedure watch writes.

KeyTypeDefaultWhat it does
procedures.enabledbooleantrueTurns procedures on.
procedures.dirstring".agentx/procedures"Folder that holds procedures.
procedures.extractionobject{}Settings for finding new procedures.
procedures.extraction.enabledbooleanfalseTurns finding new procedures on.
procedures.extraction.onTaskCompletionbooleanfalseCounts repeated patterns after each finished task. Uses no model.
procedures.extraction.minOccurrencesnumber (2 or more)3How often a pattern must repeat before it becomes a draft.
procedures.extraction.sinceDaysnumber (1 or more)7How many days of past work to look at.
procedures.extraction.maxClustersnumber (1 or more)5Most drafts made in one run.
procedures.extraction.viastring—Agent whose session writes the drafts.
procedures.injectionobject{}Giving procedures to agents.
procedures.injection.enabledbooleantrueAdds matching procedures to a new agent conversation as guidance.
procedures.injection.maxProceduresnumber (1 or more)2Most procedures added at once.
procedures.injection.minScorenumber (0–1)0.5How closely a procedure must match the request to be added.

notifications ​

Messages about finished, failed or long tasks. See get notified.

KeyTypeDefaultWhat it does
notifications.longTaskThresholdnumber30Seconds a task must run before you are told about it. 0 turns this off.
notifications.destinationobject—Where task messages go. Unset: no task messages.
notifications.destination.channelstringrequiredChannel, for example telegram or push.
notifications.destination.chatIdstringrequiredThe chat on that channel.
notifications.destination.accountIdstring—Which account on that channel.
notifications.channelstring—Where agentx notify and messages held during Focus go when no channel is given, for example push or ntfy. Unset: push when channels.push.enabled is on, otherwise ntfy.
notifications.onobject{}Which events send a message.
notifications.on.taskCompletebooleantrueA long task finished.
notifications.on.taskErrorbooleantrueA task failed.
notifications.on.taskQueuedbooleanfalseA task had to wait in the queue.
notifications.localobject{}What agentx notify does on this Mac. macOS only.
notifications.local.bannerbooleantrueShows a desktop banner.
notifications.local.soundbooleantruePlays a sound.
notifications.local.soundNamestring"Glass"A sound from /System/Library/Sounds, without the extension.
notifications.local.volumenumber (0–1)0.4Sound volume.
notifications.local.iconstring—Image for the banner icon (.png, .jpg or .icns). Unset: the AgentX logo. Applied by agentx desktop install.

calls ​

Agents ringing you for a live voice call on the desktop assistant. See Calls from your agents. The same settings cover an agent asking to see through your phone camera (Share your phone camera): a camera ask counts as a call here.

KeyTypeDefaultWhat it does
calls.allowstring[][]Agents that may call you, or ask to see: ids, or "*" for every agent. Empty: nobody.
calls.maxPerHournumber (1–60)3Most calls and camera asks one agent may place in an hour, together.
calls.ringSecondsnumber (10–300)45Seconds a call rings, or a camera ask waits on the phone, before it counts as missed.
calls.maxCallMinutesnumber (1–240)30An answered call nobody hung up ends after this many minutes (the widget quit or crashed, the Mac slept), so the agent can call again.
calls.ringSoundstring"Submarine"The ring: a sound from /System/Library/Sounds, without the extension.
calls.summarybooleantrueAfter hang-up, the agent writes a short summary, filed in the dashboard's Ask history.

approvals ​

The Approvals inbox. See Approvals.

KeyTypeDefaultWhat it does
approvals.defaultExpiryDaysnumber (up to 365)3Days a decision card waits when the agent gave no expiry.
approvals.maxExpiryDaysnumber (up to 365)30The longest any card may wait.
approvals.laterHoursnumber (up to 720)24Hours Later hides an item.
approvals.notifyAgentbooleantrueTells the agent that raised a card when it is decided or expires.
approvals.digestobject{}One reminder a day of what is waiting.
approvals.digest.enabledbooleantrueSends the daily reminder.
approvals.digest.timestring"09:00"Time of day, 24-hour HH:MM.
approvals.digest.timezonestring—Timezone for time, for example Europe/Paris. Unset: this machine's.
approvals.digest.destinationobject—Where the reminder goes. Unset: notifications.destination.
approvals.digest.destination.channelstringrequiredChannel for the reminder.
approvals.digest.destination.chatIdstringrequiredThe chat on that channel.
approvals.digest.destination.accountIdstring—Which account on that channel.

shutdown ​

How a daemon stop treats tasks that are still running. See restart without losing work.

KeyTypeDefaultWhat it does
shutdown.drainTimeoutSecondsnumber (0–86400)—How long a stop waits for running tasks before stopping them. Unset: AGENTX_DRAIN_TIMEOUT_MS from .env, else 300. An agent's own drainTimeoutSeconds can make the wait longer. Keep the service's stop time above it.
shutdown.restart.allowBystring (regular expression)—Who may ask for "restart when idle" right away, matched against the request's by (for example ^(operator|restart-window)). Requests from anyone else are held until window, or refused when there is no window. Unset: anyone.
shutdown.restart.windowstring HH:MM (local time)—When held requests start their wait for an idle moment.
shutdown.restart.windowWaitMinutesnumber (1–1440)180How long that wait lasts before it gives up without restarting.
shutdown.restart.forbidOnTimeoutRestartbooleanfalseTurns every request into an idle-only one: a wait that runs out gives up instead of restarting over running work.

resume ​

What happens to work a restart cut off. Chat messages are picked up again in their chat; scheduled jobs never are, because their next run covers them. See restart without losing work.

KeyTypeDefaultWhat it does
resume.enabledbooleantruePicks up cut-off work after a restart.
resume.maxAgeMinutesnumber (1 or more)30Work older than this is reported, not picked up.
resume.maxAttemptsnumber1How many times a run is picked up again if it keeps getting cut off.
resume.reportOnlyChannelslist of strings[]Channels whose runs are only reported, even from a chat.
resume.directChannelslist of strings[]Other channels (voice, webhooks, the API) whose runs are picked up again. Their answer is not delivered anywhere. An agent-to-agent run that names the agent which asked is always picked up: its answer goes to that agent.
resume.crashLoopobject{}Stops picking up work when the daemon keeps restarting.
resume.crashLoop.restartsnumber (1 or more)3This many restarts…
resume.crashLoop.windowMinutesnumber10…within this many minutes pauses picking up work.

reminders ​

Hands due Apple Reminders back to the agent that created them. macOS only, off by default. See Hand due reminders back to agents.

KeyTypeDefaultWhat it does
reminders.enabledbooleanfalseTurns the hand-back on. Ignored, with a log line, on machines other than a Mac.
reminders.listslist of strings["AgentX"]Reminders lists to watch.
reminders.pollSecondsnumber (15 or more)60How often the lists are read.
reminders.lookbackHoursnumber24A reminder overdue by more than this (the daemon was off) is reported to its agent, not run.
reminders.commandstring"remindctl"The remindctl program, or its full path when the daemon can't find it.

Check it worked ​

  1. Terminal: in the folder with agentx.json, run agentx config check. It prints ✓ Config valid.
  2. Terminal: run agentx config get <path> for the key you changed, for example agentx config get workflows.matching.mode. It prints the new value.
  3. Terminal: for a job, run agentx schedule list. The job appears with its schedule.

If something is wrong ​

  • config check says a cron needs a prompt or a command: add one of them to that job.
  • config check rejects autonomy on a job: the job has a command. Remove autonomy or the command.
  • A webhook is refused with 401: the entry has secretEnv, but that variable is missing from .env or holds a different secret. Fix it and restart the daemon.
  • A job stopped running: it may have been turned off after 3 failures (onError includes disable). Fix the cause, then set enabled back to true.

Released under the MIT License.