Documentation Index
Fetch the complete documentation index at: https://docs.actionllama.org/llms.txt
Use this file to discover all available pages before exploring further.
Each agent lives in a directory under 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 |
A skill is the portable artifact (SKILL.md + optionally a Dockerfile). An agent is a skill instantiated in your project with local runtime config. When you 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.
agents/<name>/
├── SKILL.md # Portable metadata + instructions
├── config.toml # Project-local runtime config
└── Dockerfile # Optional — custom container image (container runtime only)
SKILL.md
The YAML frontmatter contains portable metadata. The markdown body contains the agent’s instructions.
---
name: dev-agent
description: Solves GitHub issues by writing and testing code
license: MIT
compatibility: ">=0.5.0"
---
# Instructions
You are a dev agent. Check for open issues labeled "agent" and fix them.
## Workflow
1. List open issues labeled "agent" in repos from `<agent-config>`
2. For each issue, clone the repo, create a branch, implement the fix
3. Open a PR and link it to the issue
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-agent config.toml contains project-specific runtime configuration. This file is created by al add, al agent new, or al config.
# Install origin — used by `al update` to pull upstream SKILL.md changes
source = "acme/dev-skills"
# Required: named model references from project config.toml [models.*]
# First in list is primary; rest are fallbacks tried on rate limits
models = ["sonnet", "haiku"]
# Optional: override the project default harness for this agent
[harness]
type = "claude" # "pi" (default) or "claude"
# Required: credential types the agent needs at runtime
# Use "type" for default instance, "type:instance" for named instance
credentials = ["github_token", "git_ssh", "sentry_token"]
# Optional: cron schedule (standard cron syntax)
# Agent must have at least one of: schedule, webhooks
schedule = "*/5 * * * *"
# Optional: number of concurrent runs allowed (default: 1)
# When scale > 1, use acquire_lock/release_lock in your actions to coordinate
scale = 2
# Optional: max runtime in seconds (default: falls back to [local].timeout, then 900)
timeout = 600
# Optional: max queued work items for this agent (default: global workQueueSize)
# When all runners are busy, incoming events are queued up to this limit.
# Oldest events are dropped to make room for newer ones.
maxWorkQueueSize = 50
# Optional: max wait timeout for wait_for_trigger in seconds (default: global defaultWaitTimeout or 1800)
waitTimeout = 3600
# Optional: webhook triggers (instead of or in addition to schedule)
[[webhooks]]
source = "my-github"
repos = ["acme/app"]
events = ["issues"]
actions = ["labeled"]
labels = ["agent"]
[[webhooks]]
source = "my-sentry"
resources = ["error", "event_alert"]
[[webhooks]]
source = "my-linear"
events = ["issues"]
actions = ["create", "update"]
labels = ["bug"]
[[webhooks]]
source = "my-mintlify"
events = ["build"]
actions = ["failed"]
# Optional: hooks — shell commands that run before or after the LLM session
[hooks]
pre = [
"gh repo clone acme/app /tmp/repo --depth 1",
"curl -o /tmp/context/flags.json https://api.internal/v1/flags",
"gh issue list --repo acme/app --label P1 --json number,title,body --limit 20 > /tmp/context/issues.json",
]
post = ["upload-artifacts.sh"]
# Optional: custom parameters injected into the agent prompt
[params]
repos = ["acme/app", "acme/api"]
triggerLabel = "agent"
assignee = "bot-user"
sentryOrg = "acme"
sentryProjects = ["web-app", "api"]
# Optional: runtime mode — "container" (default) or "host-user"
# Host-user runs the agent as a separate OS user via sudo, without Docker.
# Useful when the agent needs to run Docker commands itself.
[runtime]
type = "host-user"
run_as = "al-agent" # OS user to run as (default: "al-agent")
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. |
harness | table | No | Harness override for this agent. Falls back to project [harness], then defaults to pi. |
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 acquire_lock/release_lock 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. |
waitTimeout | number | No | Maximum wait timeout for wait_for_trigger in seconds. Falls back to global defaultWaitTimeout (default: 1800 / 30 minutes). See Wait & Resume. |
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. |
*At least one of schedule or webhooks is required (unless scale = 0).
Harness
The optional [harness] table selects which harness runs this agent.
[harness]
type = "claude"
Fields
| Field | Type | Default | Description |
|---|
type | string | Inherits project [harness] or "pi" | "pi" or "claude" |
Notes
pi is the default harness and supports the full model fallback chain.
claude runs the agent through the Claude CLI harness and uses the agent’s primary model only.
- Per-agent
[harness] overrides the project-level [harness].
- The
claude harness is intended for Anthropic Claude models.
Scale
The scale 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
workQueueSize limit 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
See Scaling Agents for a guide on scaling with resource locks.
Timeout
The timeout 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
# Fast webhook responder
timeout = 300 # 5 minutes
# Medium-length task
timeout = 900 # 15 minutes
# Long-running agent
timeout = 3600 # 1 hour
# Omit timeout — uses [local].timeout or defaults to 900s
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
[hooks]
pre = [
"gh repo clone acme/app /tmp/repo --depth 1",
"gh issue list --repo acme/app --label P1 --json number,title,body --limit 20 > /tmp/context/issues.json",
"curl -o /tmp/context/flags.json https://api.internal/v1/flags",
]
post = ["upload-artifacts.sh"]
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.
[runtime]
type = "host-user"
run_as = "al-agent"
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. Run al doctor to validate and auto-configure (Linux only):
On Linux, 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
On macOS, al doctor prints manual setup instructions.
Limitations
- No custom Dockerfiles —
Dockerfile in 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
needsGateway is false — the gateway is not started for host-user-only projects
Webhook Trigger Fields
Each entry in the webhooks 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") |
All filter fields below are optional. Omit all of them to trigger on everything from that source. See Webhooks for complete filter field tables per provider.
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
The models 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.
models = ["sonnet", "haiku", "gpt4o"]
See Models for all supported providers, model IDs, auth types, thinking levels, and credential setup.