Agent Guide
The Crontinel agent is a lightweight daemon that runs on your server, connects to app.crontinel.com, and polls for remote commands. It enables cloud-triggered cron execution — schedule a command from the dashboard and the agent runs it on your server.
How It Works
- The agent registers with Crontinel Cloud using your API key and app ID
- It connects to receive commands — see Connection Method below, since this differs by runtime
- When a trigger is scheduled from the dashboard, the agent checks the command against your configured allowlist
- If allowed, it executes the command and reports the result (success/failure, output, duration) back to the cloud; if not allowed, it reports a rejection and does not run it
- A heartbeat is sent every 60 seconds to confirm the agent is alive
Connection Method
The Laravel agent and the Node.js/Python agents use different transports to receive commands:
- Laravel opens a persistent SSE (Server-Sent Events) connection to
/v1/agent/streamand receives commands as they’re dispatched, with no polling interval. Heartbeats are sent separately via/v1/agent/heartbeatevery 60 seconds. - Node.js and Python poll
app.crontinel.com/api/v1/agents/{id}/commandsevery 5 seconds, and send heartbeats via/api/v1/agents/heartbeatevery 60 seconds.
Both approaches deliver the same behavior from your perspective — commands run within seconds of being scheduled — the underlying connection just differs by runtime.
Laravel Agent
The Laravel package (crontinel/laravel) includes a built-in agent command.
Prerequisites
crontinel/laravelinstalled via ComposerCRONTINEL_API_KEYandCRONTINEL_APP_IDset in.env
Start the Agent
php artisan crontinel:agentProduction Setup
Generate a systemd unit file:
php artisan crontinel:agent --systemdOr a supervisor config:
php artisan crontinel:agent --supervisorNode.js Agent
The Node package (@crontinel/node) includes a CLI agent.
Prerequisites
@crontinel/nodeinstalled via npmCRONTINEL_API_KEYandCRONTINEL_APP_IDenvironment variables set
Start the Agent
npx crontinel agentOr with environment variables inline:
CRONTINEL_API_KEY=your-key CRONTINEL_APP_ID=your-app npx crontinel agentPython Agent
The Python package includes an agent CLI (requires PyPI installation when available).
Prerequisites
crontinelpackage installedCRONTINEL_API_KEYandCRONTINEL_APP_IDenvironment variables set
Start the Agent
crontinel agentCommand Allowlisting
The agent will only execute commands that match an entry in your allowlist. An unconfigured or empty allowlist means no commands are permitted — this is the default, fail-closed behavior.
Patterns support exact string matches and * as a wildcard (e.g. php artisan queue:* allows any queue: subcommand).
Laravel — publish the config (php artisan vendor:publish --tag=crontinel-config) and set allowed_commands in the agent block of config/crontinel.php:
'agent' => [ // ... 'allowed_commands' => [ 'php artisan queue:restart', 'php artisan horizon:terminate', 'php artisan queue:*', ],],Node.js and Python — set the CRONTINEL_AGENT_ALLOWED_COMMANDS environment variable to a comma-separated list of patterns:
CRONTINEL_AGENT_ALLOWED_COMMANDS="php artisan queue:restart,php artisan horizon:terminate,queue:*" npx crontinel agentThe Node.js and Python agents also accept an equivalent allowedCommands / allowed_commands option when constructing the agent programmatically.
A rejected command is reported back to the dashboard as failed with the reason “Command rejected: not in allowlist,” so you can see rejections in your trigger history and adjust the allowlist as needed.
Systemd Service (All Runtimes)
Create /etc/systemd/system/crontinel-agent.service:
[Unit]Description=Crontinel Agent DaemonAfter=network.target
[Service]Type=simpleUser=www-dataWorkingDirectory=/path/to/your/appEnvironment=CRONTINEL_API_KEY=your-api-keyEnvironment=CRONTINEL_APP_ID=your-app-slugExecStart=/usr/bin/php artisan crontinel:agentRestart=alwaysRestartSec=10
[Install]WantedBy=multi-user.targetEnable and start:
sudo systemctl enable crontinel-agentsudo systemctl start crontinel-agentSupervisor Config (All Runtimes)
Create /etc/supervisor/conf.d/crontinel-agent.conf:
[program:crontinel-agent]command=php artisan crontinel:agentdirectory=/path/to/your/appuser=www-dataautostart=trueautorestart=truestartretries=3stderr_logfile=/var/log/crontinel-agent.err.logstdout_logfile=/var/log/crontinel-agent.out.logReload and start:
sudo supervisorctl rereadsudo supervisorctl updatesudo supervisorctl start crontinel-agentEnvironment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
CRONTINEL_API_KEY | Yes | — | Your API key from app.crontinel.com/settings |
CRONTINEL_APP_ID | Yes | — | Your app slug from the app settings page |
CRONTINEL_API_URL | No | https://app.crontinel.com | API base URL (change only for self-hosted) |
CRONTINEL_AGENT_ALLOWED_COMMANDS | Node/Python only | — (fail-closed) | Comma-separated allowlist patterns. Laravel uses allowed_commands in config/crontinel.php instead — see Command Allowlisting |
Testing
- Add the command you want to test to your allowlist — untested commands are rejected by default
- Go to your app detail page
- Click “Schedule Trigger”
- Enter the same command (e.g.,
php artisan inspire) - Set it to run “Now”
- Watch the agent execute it and report back
Troubleshooting
Agent won’t start
- Verify
CRONTINEL_API_KEYandCRONTINEL_APP_IDare set - Check network connectivity to
app.crontinel.com
Agent starts but no commands received
- Verify the app ID matches your app in the dashboard
- Check that triggers are being dispatched (Dashboard → Triggers)
Agent crashes repeatedly
- Enable logging: set
CRONTINEL_AGENT_LOG=/var/log/crontinel-agent.log - Ensure the agent user has permission to execute the scheduled commands
Commands are rejected / never execute
- Check the trigger’s result on the dashboard for “Command rejected: not in allowlist”
- Verify the command matches an entry in your allowlist exactly, or via a
*pattern - Remember the default allowlist is empty — nothing runs until you configure one