agents/<name>/. Configuration is split across two files:
| File | Purpose | Portable? |
|---|---|---|
SKILL.md | Portable metadata (name, description, license, compatibility) + markdown instructions | Yes — travels with the skill |
config.toml | Runtime config (credentials, models, schedule, webhooks, hooks, params, scale, timeout) | No — project-local |
al add a skill, it becomes an agent.
An optional Dockerfile can also live in the agent directory for custom container images. It may be provided by the skill author or customized per-project.
SKILL.md
The YAML frontmatter contains portable metadata. The markdown body contains the agent’s instructions.SKILL.md Frontmatter Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Human-readable name (defaults to directory name) |
description | string | No | Short description of what the agent does |
license | string | No | License identifier (e.g. "MIT") |
compatibility | string | No | Semver range for Action Llama compatibility |
config.toml
The per-agentconfig.toml contains project-specific runtime configuration. This file is created by al add, al agent new, or al config.
config.toml Field Reference
| Field | Type | Required | Description |
|---|---|---|---|
source | string | No | Git URL or GitHub shorthand for al update. Set automatically by al add. |
models | string[] | Yes | Named model references from config.toml [models.*]. First is primary; rest are fallbacks tried automatically on rate limits. |
credentials | string[] | Yes | Credential refs: "type" for default instance, "type:instance" for named instance. See Credentials. |
schedule | string | No* | Cron expression for polling |
scale | number | No | Number of concurrent runs allowed (default: 1). Set to 0 to disable the agent. Use lock skills in your actions to coordinate instances. See Resource Locks. |
timeout | number | No | Max runtime in seconds. Falls back to [local].timeout in project config, then 900. See Timeout. |
maxWorkQueueSize | number | No | Maximum queued work items when all runners are busy. Falls back to global workQueueSize (default: 20). Oldest events are dropped to make room for newer ones. |
webhooks | array | No* | Array of webhook trigger objects. See Webhooks. |
hooks | table | No | Pre/post hooks that run around the LLM session. See Hooks. |
params | table | No | Custom key-value params for the agent prompt |
runtime | table | No | Runtime mode configuration. See Runtime. |
schedule or webhooks is required (unless scale = 0).
Scale
Thescale field controls how many instances of an agent can run concurrently.
- Default: 1 (only one instance can run at a time)
- Minimum: 0 (disables the agent — no runners, cron jobs, or webhook bindings are created)
- Maximum: No hard limit, but consider system resources and model API rate limits
How it works
- Scheduled runs: If a cron trigger fires but all agent instances are busy, the scheduled run is skipped with a warning
- Webhook events: If a webhook arrives but all instances are busy, the event is queued (up to
workQueueSizelimit in global config, default: 100) - Agent calls: If one agent calls another but all target instances are busy, the call is queued in the same work queue
Example use cases
- Dev agent with
scale = 3: Handle multiple GitHub issues simultaneously - Review agent with
scale = 2: Review multiple PRs in parallel - Monitoring agent with
scale = 1: Ensure only one instance processes alerts at a time - Disabled agent with
scale = 0: Keep the config in the project but don’t run it
Resource considerations
Each parallel instance:- Uses a separate Docker container (or OS process in host-user mode)
- Has independent logging streams
- May consume LLM API quota concurrently
- Uses system memory and CPU
Timeout
Thetimeout field controls the maximum runtime for an agent invocation. When the timeout expires, the process is terminated with exit code 124.
Resolution order: config.toml timeout -> project config.toml [local].timeout -> 900 (default)
This means you can set a project-wide default in [local].timeout and override it per-agent.
Examples
Hooks
Hooks run shell commands before and after the LLM session. Pre-hooks (hooks.pre) run after credentials are loaded but before the LLM session starts — use them for cloning repos, fetching data, or staging files. Post-hooks (hooks.post) run after the session completes — use them for cleanup, artifact upload, or reporting.
See Dynamic Context for a guide on using hooks effectively.
How it works
- Commands run sequentially in the order they appear in
config.toml - Commands run inside the agent’s execution environment (container or host-user process) after credential/env setup
- Each command runs via
/bin/sh -c "..." - If any command exits non-zero, the run aborts with an error
- Credential env vars (
GITHUB_TOKEN,GH_TOKEN, etc.) are available to hook commands
Fields
| Field | Type | Required | Description |
|---|---|---|---|
hooks.pre | string[] | No | Shell commands to run before the LLM session |
hooks.post | string[] | No | Shell commands to run after the LLM session |
Examples
Notes
- Each hook has a 5-minute timeout
- Hooks are bounded by the container-level timeout
- Environment variables set inside hook commands do not propagate back to the agent’s
process.env
Runtime
The[runtime] table controls how the agent process is launched. By default, agents run in Docker containers. The host-user runtime runs agents as a separate OS user on the host machine via sudo -u, without Docker.
Host-user mode is useful when agents need to run Docker commands themselves (Docker-in-Docker is insecure), or when you want lightweight isolation without container overhead.
Fields
| Field | Type | Default | Description |
|---|---|---|---|
type | string | "container" | Runtime mode: "container" (Docker) or "host-user" (OS user isolation) |
run_as | string | "al-agent" | OS username to run the agent as. Only used when type = "host-user". |
How host-user mode works
- The scheduler spawns
sudo -u <run_as> al _run-agent <agent> --project <dir> - Credentials are staged to a temp directory and chowned to the agent user
- Each run gets an isolated working directory at
/tmp/al-runs/<instance-id>/ - Logs are written to
/tmp/al-runs/<instance-id>.log(owned by the scheduler, not the agent) - No Docker images are built for host-user agents
Setup
The agent OS user must exist and sudoers must be configured. Runal doctor to validate and auto-configure (Linux only):
al doctor will:
- Create the OS user if it doesn’t exist (
useradd --system --shell /usr/sbin/nologin <run_as>) - Add a sudoers rule allowing passwordless execution
al doctor prints manual setup instructions.
Limitations
- No custom Dockerfiles —
Dockerfilein the agent directory is ignored - No container filesystem isolation — the agent runs on the host filesystem
- The
[local]config section (memory,cpus,image) does not apply to host-user agents needsGatewayis false — the gateway is not started for host-user-only projects
Webhook Trigger Fields
Each entry in thewebhooks array has the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
source | string | Yes | Name of a webhook source from the project’s config.toml (e.g. "my-github") |
GitHub filter fields
| Field | Type | Description |
|---|---|---|
repos | string[] | Filter to specific repos |
orgs | string[] | Filter to specific organizations |
org | string | Filter to a single organization |
events | string[] | Event types: issues, pull_request, push, etc. |
actions | string[] | Event actions: opened, labeled, closed, etc. |
labels | string[] | Only trigger when issue/PR has these labels |
assignee | string | Only trigger when assigned to this user |
author | string | Only trigger for this author |
branches | string[] | Only trigger for these branches |
conclusions | string[] | Only for workflow_run events with these conclusions |
Sentry filter fields
| Field | Type | Description |
|---|---|---|
resources | string[] | Resource types: event_alert, metric_alert, issue, error, comment |
Linear filter fields
| Field | Type | Description |
|---|---|---|
organizations | string[] | Filter to specific Linear organizations |
events | string[] | Linear event types: issues, issue_comment, etc. |
actions | string[] | Event actions: create, update, delete, etc. |
labels | string[] | Only when issue has these labels |
assignee | string | Only when assigned to this user (email) |
author | string | Only for this author (email) |
Mintlify filter fields
| Field | Type | Description |
|---|---|---|
projects | string[] | Filter to specific Mintlify projects |
events | string[] | Mintlify event types: build, etc. |
actions | string[] | Event actions: failed, succeeded, etc. |
branches | string[] | Only for these branches |
Model Configuration
Themodels field references named models defined in config.toml under [models.<name>]. List one or more model names — the first is the primary model, and subsequent entries are fallbacks tried automatically when the primary is rate-limited or unavailable.