Schedules and channels
Most runs start from an HTTP request. Triggers are the other two ways a run
begins: a schedule fires a prompt on a clock, and a channel fires on an
inbound event. Both run only while the agent is served (maiden serve), and both
share the same single runtime lock as the HTTP server — so a triggered run and a
request never overlap.
Schedules
Section titled “Schedules”A schedule fires a fixed prompt on a fixed interval. Create a file under
schedules/:
prompt = "summarize anything new since the last tick"every_seconds = 300| Key | Type | Description |
|---|---|---|
prompt | string | The message sent on each fire. |
every_seconds | integer | Seconds between fires. |
Each schedule runs on its own thread, named after the file. The prompt runs through the normal agent loop, so it can call tools and its history accumulates on that thread.
Channels
Section titled “Channels”A channel starts a run from an inbound event. Today the only kind is
file-drop: maiden watches a directory, and each JSON file dropped into it
becomes a message.
kind = "file-drop"dir = "/var/spool/my-agent-inbox"| Key | Type | Description |
|---|---|---|
kind | string | Channel type. Must be file-drop. |
dir | string | Directory to watch for *.json files. |
Drop a file like {"message": "process order 1234"} into that directory, and
maiden runs the agent with that message. Each file is processed exactly once:
after the run, the file is moved into a .processed/ subdirectory, so a restart
never re-runs an already-handled message.
echo '{"message":"hello from a dropped file"}' > /var/spool/my-agent-inbox/msg.jsonRunning triggers
Section titled “Running triggers”Triggers start automatically with the server:
maiden serve my-agent# [trigger] schedule 'heartbeat' every 300s# [trigger] channel 'inbox' watching /var/spool/my-agent-inboxThey log each run’s outcome to stderr. Because everything shares one lock, a busy schedule or channel will queue behind in-flight work rather than run in parallel — see Execution model.