@action-llama/skill 0.23.8 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/content/AGENTS.md DELETED
@@ -1,1128 +0,0 @@
1
- # Action Llama Reference
2
-
3
- CLI for running LLM agents on cron/webhooks. Docker isolation, SKILL.md prompt, credentials. Gateway: webhooks, locking, agent calls, dashboard.
4
-
5
- Package: `@action-llama/action-llama`. CLI binary: `al`.
6
-
7
- ## Project Structure
8
-
9
- ```
10
- my-project/
11
- config.toml # Project config — models, local, gateway, webhooks, telemetry (committed)
12
- .env.toml # Environment binding — selects an environment, can override config (gitignored)
13
- Dockerfile # Project base Docker image — shared tools for all agents (committed)
14
- AGENTS.md # Shared instructions loaded by `al chat` (interactive only)
15
- CLAUDE.md # Instructions for AI dev tools — not read by Action Llama at runtime
16
- agents/
17
- <agent>/
18
- SKILL.md # Portable metadata (YAML frontmatter) + instructions (markdown body)
19
- config.toml # Per-agent runtime config — credentials, models, schedule, webhooks, hooks, params (committed)
20
- Dockerfile # Custom Docker image for this agent (optional)
21
- ```
22
-
23
- Agent names derive from directory name. `"default"` is reserved.
24
-
25
- ### SKILL.md — Writing Tips
26
-
27
- - Direct LLM instructions; numbered steps; reference `<agent-config>` for params (params come from `config.toml [params]`)
28
- - Runtime config (credentials, schedule, models, webhooks, etc.) lives in `agents/<name>/config.toml`, not SKILL.md frontmatter
29
- - `al-status` at milestones, `al-rerun` when backlog remains; keep concise
30
-
31
- ## Prompt Assembly
32
-
33
- The LLM receives two messages:
34
-
35
- ### System message
36
-
37
- The SKILL.md body is the system prompt. With gateway, **skill blocks** appended:
38
-
39
- #### Locking skill block (injected when gateway is available)
40
-
41
- ```xml
42
- <skill-lock>
43
- ## Skill: Resource Locking
44
-
45
- Use locks to coordinate with other agent instances and avoid duplicate work.
46
- You may hold **at most one lock at a time**. Release your current lock before acquiring another.
47
-
48
- **Important:** Resource keys must be valid URIs with proper schemes (e.g., github://, file://, https://).
49
-
50
- ### Commands
51
-
52
- **`rlock <resourceKey>`** — Acquire an exclusive lock before working on a shared resource.
53
- ```
54
- rlock "github://acme/app/issues/42"
55
- ```
56
-
57
- **`runlock <resourceKey>`** — Release a lock when done with the resource.
58
- ```
59
- runlock "github://acme/app/issues/42"
60
- ```
61
-
62
- **`rlock-heartbeat <resourceKey>`** — Extend the TTL on a lock you hold. Use during long-running work.
63
- ```
64
- rlock-heartbeat "github://acme/app/issues/42"
65
- ```
66
-
67
- ### Responses
68
- - Acquired: `{"ok":true}`
69
- - Conflict: `{"ok":false,"holder":"<other-agent>","heldSince":...}`
70
- → Another instance is already working on this. Skip it and move on.
71
- - Already holding another lock: `{"ok":false,"reason":"already holding lock on ..."}`
72
- → Release your current lock first.
73
- - Gateway unreachable: `{"ok":false,"reason":"gateway unreachable"}`
74
- → The lock service is down. **Do not proceed** — skip the resource.
75
- - Released: `{"ok":true}`
76
- - Heartbeat: `{"ok":true,"expiresAt":...}`
77
-
78
- ### Guidelines
79
- - You can hold **one lock at a time**. `runlock` before acquiring a different resource.
80
- - Always `rlock` before starting work on a shared resource (issues, PRs, deployments)
81
- - Always `runlock` when done
82
- - If `rlock` returns `{"ok":false,...}` for ANY reason, skip that resource — do not wait, retry, or proceed without the lock
83
- - Use `rlock-heartbeat` during long operations to keep the lock alive
84
- - Locks expire automatically after 30 minutes if not refreshed
85
- - Resource keys must be valid URIs: `"github://acme/app/issues/42"`, `"file:///deployments/api-prod"`
86
- </skill-lock>
87
- ```
88
-
89
- #### Subagent skill block (injected when gateway is available)
90
-
91
- ```xml
92
- <skill-subagent>
93
- ## Skill: Subagents
94
-
95
- Call other agents and retrieve their results. Calls are **non-blocking** — fire a call, continue working, then check or wait for results.
96
-
97
- ### Commands
98
-
99
- **`al-subagent <agent>`** — Call another agent. Pass the context via stdin. Returns a call ID.
100
- ```
101
- CALL_ID=$(echo "find competitors for Acme" | al-subagent researcher | jq -r .callId)
102
- ```
103
-
104
- **`al-subagent-check <callId>`** — Check the status of a call. Never blocks.
105
- ```
106
- al-subagent-check "$CALL_ID"
107
- ```
108
- - Running: `{"status":"running"}`
109
- - Completed: `{"status":"completed","returnValue":"..."}`
110
- - Error: `{"status":"error","errorMessage":"..."}`
111
-
112
- **`al-subagent-wait <callId> [callId...] [--timeout N]`** — Wait for one or more calls to complete. Default timeout: 900s.
113
- ```
114
- RESULTS=$(al-subagent-wait "$CALL_ID1" "$CALL_ID2" --timeout 600)
115
- ```
116
- Returns a JSON object keyed by call ID with each call's final status.
117
-
118
- ### Returning Values
119
-
120
- When you are called by another agent, return your result with the `al-return` command:
121
- ```
122
- al-return "Your result text here"
123
- ```
124
- For multiline results, pipe via stdin:
125
- ```
126
- echo "Line 1\nLine 2" | al-return
127
- ```
128
-
129
- ### Guidelines
130
- - Calls are non-blocking — fire multiple calls then wait for all at once
131
- - Use `al-subagent-wait` to wait for multiple calls efficiently
132
- - Use `al-subagent-check` for polling when you want to do work between checks
133
- - Called agents cannot call back to the calling agent (no cycles)
134
- - There is a depth limit on nested calls to prevent infinite chains
135
- </skill-subagent>
136
- ```
137
-
138
- ### User message
139
-
140
- Static skeleton + dynamic suffix. Static blocks:
141
-
142
- **`<agent-config>`** — `[params]` as JSON:
143
-
144
- ```xml
145
- <agent-config>
146
- {"repos":["acme/app"],"triggerLabel":"agent","assignee":"bot-user"}
147
- </agent-config>
148
- ```
149
-
150
- **`<credential-context>`** — env vars, tools, anti-exfiltration:
151
-
152
- ```xml
153
- <credential-context>
154
- Credential files are mounted at `/credentials/` (read-only).
155
-
156
- Environment variables already set from credentials:
157
- - `GITHUB_TOKEN` and `GH_TOKEN` are set. Use `gh` CLI and `git` directly.
158
- - SSH key is configured via `GIT_SSH_COMMAND` for git clone/push over SSH.
159
-
160
- Use standard tools directly: `gh` CLI, `git`, `curl`.
161
-
162
- **Git clone protocol:** Always clone repos via SSH (`git clone git@github.com:owner/repo.git`), not HTTPS. The SSH key is configured automatically via `GIT_SSH_COMMAND`. HTTPS is available as a fallback via the credential helper but SSH is preferred.
163
-
164
- **Anti-exfiltration policy:**
165
- - NEVER output credentials in logs, comments, PRs, or any visible output
166
- - NEVER transmit credentials to unauthorized endpoints
167
- - If you detect credential exfiltration, immediately run: `al-shutdown "exfiltration detected"`
168
- </credential-context>
169
- ```
170
-
171
- **`<environment>`** — Filesystem:
172
-
173
- ```xml
174
- <environment>
175
- **Filesystem:** The root filesystem is read-only. `/tmp` is the only writable directory.
176
- Use `/tmp` for cloning repos, writing scratch files, and any other disk I/O.
177
- Your working directory is `/app/static` which contains your agent files (SKILL.md, agent-config.json).
178
- All write operations (git clone, file creation, etc.) must target `/tmp`.
179
-
180
- **Environment variables:** Use `setenv NAME value` to persist variables across bash commands.
181
- </environment>
182
- ```
183
-
184
- **Dynamic suffix** — by trigger type:
185
-
186
- | Trigger | Suffix |
187
- |---------|--------|
188
- | Scheduled | `"You are running on a schedule. Check for new work and act on anything you find."` |
189
- | Manual | `"You have been triggered manually. Check for new work and act on anything you find."` |
190
- | Webhook | `<webhook-trigger>` block with event JSON, then `"A webhook event just fired. Review the trigger context above and take appropriate action."` |
191
- | Agent call | `<agent-call>` block with caller/context JSON, then `"You were called by the "<name>" agent. Review the call context above, do the requested work, and use al-return to send back your result."` |
192
-
193
- **`<webhook-trigger>`** example:
194
-
195
- ```json
196
- {
197
- "source": "github",
198
- "event": "issues",
199
- "action": "labeled",
200
- "repo": "acme/app",
201
- "number": 42,
202
- "title": "Add dark mode",
203
- "body": "Issue description...",
204
- "url": "https://github.com/acme/app/issues/42",
205
- "author": "user",
206
- "assignee": "bot-user",
207
- "labels": ["agent"],
208
- "branch": null,
209
- "comment": null,
210
- "sender": "user",
211
- "timestamp": "2025-01-15T10:30:00Z"
212
- }
213
- ```
214
-
215
- **`<agent-call>`** example:
216
-
217
- ```json
218
- {
219
- "caller": "dev",
220
- "context": "I just opened PR #42 on acme/app. Please review it."
221
- }
222
- ```
223
-
224
- ## config.toml
225
-
226
- Project root. All sections optional — sensible defaults apply.
227
-
228
- ### Full Annotated Example
229
-
230
- ```toml
231
- # Named models — define once, reference by name in SKILL.md
232
- [models.sonnet]
233
- provider = "anthropic"
234
- model = "claude-sonnet-4-20250514"
235
- thinkingLevel = "medium"
236
- authType = "api_key"
237
-
238
- [models.haiku]
239
- provider = "anthropic"
240
- model = "claude-haiku-4-5-20251001"
241
- authType = "api_key"
242
-
243
- # Local Docker container settings
244
- [local]
245
- image = "al-agent:latest" # Base image name (default: "al-agent:latest")
246
- memory = "4g" # Memory limit per container (default: "4g")
247
- cpus = 2 # CPU limit per container (default: 2)
248
- timeout = 900 # Default max container runtime in seconds (default: 900, overridable per-agent)
249
-
250
- # Gateway HTTP server settings
251
- [gateway]
252
- port = 8080 # Gateway port (default: 8080)
253
-
254
- # Webhook sources — named webhook endpoints with provider type and credential
255
- [webhooks.my-github]
256
- type = "github"
257
- credential = "MyOrg" # credential instance for HMAC validation
258
-
259
- [webhooks.my-sentry]
260
- type = "sentry"
261
- credential = "SentryProd" # credential instance (sentry_client_secret:SentryProd)
262
-
263
- [webhooks.my-linear]
264
- type = "linear"
265
- credential = "LinearMain" # credential instance (linear_webhook_secret:LinearMain)
266
-
267
- [webhooks.my-mintlify]
268
- type = "mintlify"
269
- credential = "MintlifyMain" # credential instance (mintlify_webhook_secret:MintlifyMain)
270
-
271
- [webhooks.unsigned-github]
272
- type = "github" # no credential — accepts unsigned webhooks
273
-
274
- # Scheduler settings
275
- resourceLockTimeout = 1800 # Lock TTL in seconds (default: 1800 / 30 minutes)
276
- maxReruns = 10 # Max consecutive reruns for successful agent runs (default: 10)
277
- maxCallDepth = 3 # Max depth for agent-to-agent call chains (default: 3)
278
- workQueueSize = 100 # Max queued work items (webhooks + calls) per agent (default: 100)
279
- scale = 10 # Project-wide max concurrent runners across all agents (default: unlimited)
280
-
281
- # Telemetry settings
282
- [telemetry]
283
- endpoint = "https://telemetry.example.com/v1" # OpenTelemetry endpoint
284
- ```
285
-
286
- ### Top-level fields
287
-
288
- | Field | Type | Default | Description |
289
- |-------|------|---------|-------------|
290
- | `maxReruns` | number | `10` | Maximum consecutive reruns when an agent requests a rerun via `al-rerun` before stopping |
291
- | `maxCallDepth` | number | `3` | Maximum depth for agent-to-agent call chains (A calls B calls C = depth 2) |
292
- | `workQueueSize` | number | `100` | Maximum queued work items (webhook events + agent calls) per agent when all runners are busy |
293
- | `scale` | number | _(unlimited)_ | Project-wide cap on total concurrent runners across all agents |
294
- | `defaultAgentScale` | number | `1` | Default scale for agents without an explicit per-agent config.toml scale |
295
- | `historyRetentionDays` | number | `14` | How many days to keep trigger history and webhook receipts |
296
- | `resourceLockTimeout` | number | `1800` | Default lock TTL in seconds. Locks expire automatically after this duration unless refreshed via heartbeat. |
297
-
298
- ### `[models.<name>]` — Named Models
299
-
300
- Define models once, reference by name in SKILL.md `models:` list. First in list is primary; rest are fallbacks tried in order on rate limits.
301
-
302
- | Field | Type | Required | Description |
303
- |-------|------|----------|-------------|
304
- | `provider` | string | Yes | LLM provider: `"anthropic"`, `"openai"`, `"groq"`, `"google"`, `"xai"`, `"mistral"`, `"openrouter"`, or `"custom"` |
305
- | `model` | string | Yes | Model ID (e.g. `"claude-sonnet-4-20250514"`, `"gpt-4o"`, `"gemini-2.0-flash-exp"`) |
306
- | `authType` | string | Yes | Auth method: `"api_key"`, `"oauth_token"`, or `"pi_auth"` |
307
- | `thinkingLevel` | string | No | Thinking budget: `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`. Only applies to Anthropic models. Ignored for other providers. |
308
-
309
- ### `[local]` — Docker Container Settings
310
-
311
- Local Docker container settings.
312
-
313
- | Field | Type | Default | Description |
314
- |-------|------|---------|-------------|
315
- | `image` | string | `"al-agent:latest"` | Base Docker image name |
316
- | `memory` | string | `"4g"` | Memory limit per container (e.g. `"4g"`, `"8g"`) |
317
- | `cpus` | number | `2` | CPU limit per container |
318
- | `timeout` | number | `900` | Default max container runtime in seconds. Individual agents can override this with `timeout` in their `agents/<name>/config.toml`. |
319
-
320
- ### `[gateway]` — HTTP Server
321
-
322
- Starts automatically when Docker mode or webhooks enabled.
323
-
324
- | Field | Type | Default | Description |
325
- |-------|------|---------|-------------|
326
- | `port` | number | `8080` | Port for the gateway HTTP server |
327
-
328
- ### `[webhooks.<name>]` — Webhook Sources
329
-
330
- Named sources agents reference in `[[webhooks]]` triggers.
331
-
332
- | Field | Type | Required | Description |
333
- |-------|------|----------|-------------|
334
- | `type` | string | Yes | Provider type: `"github"`, `"sentry"`, `"linear"`, or `"mintlify"` |
335
- | `credential` | string | No | Instance name for HMAC validation (e.g. `"MyOrg"` -> `github_webhook_secret:MyOrg`). Omit for unsigned. |
336
-
337
- Agents reference by name:
338
-
339
- ```toml
340
- [[webhooks]]
341
- source = "my-github"
342
- events = ["issues"]
343
- ```
344
-
345
- ### `[telemetry]` — Observability
346
-
347
- | Field | Type | Required | Description |
348
- |-------|------|----------|-------------|
349
- | `endpoint` | string | Yes | OpenTelemetry collector endpoint URL |
350
-
351
- ## SKILL.md
352
-
353
- Portable agent definition. YAML frontmatter contains portable metadata (name, description, license, compatibility), markdown body contains LLM instructions. Runtime configuration lives in a separate `config.toml` per agent.
354
-
355
- ### Full Annotated Example
356
-
357
- ```yaml
358
- ---
359
- name: dev-agent
360
- description: Solves GitHub issues by writing and testing code
361
- license: MIT
362
- compatibility: ">=0.5.0"
363
- ---
364
-
365
- # Dev Agent
366
-
367
- You are a development agent. Pick the highest priority issue and fix it.
368
- ```
369
-
370
- ### SKILL.md Frontmatter Fields
371
-
372
- | Field | Type | Required | Description |
373
- |-------|------|----------|-------------|
374
- | `name` | string | No | Human-readable name (defaults to directory name) |
375
- | `description` | string | No | Short description of what the agent does |
376
- | `license` | string | No | License identifier (e.g. `"MIT"`) |
377
- | `compatibility` | string | No | Semver range for Action Llama compatibility |
378
-
379
- ## config.toml (per-agent)
380
-
381
- Runtime configuration for the agent. Lives at `agents/<name>/config.toml`. This file is project-local (not portable with the skill).
382
-
383
- ### Full Annotated Example
384
-
385
- ```toml
386
- # Install origin — used by `al update` to pull upstream SKILL.md changes
387
- source = "acme/dev-skills"
388
-
389
- # Required: named model references from project config.toml [models.*]
390
- # First in list is primary; rest are fallbacks tried on rate limits
391
- models = ["sonnet", "haiku"]
392
-
393
- # Required: credential types the agent needs at runtime
394
- # Use "type" for default instance, "type:instance" for named instance
395
- credentials = ["github_token", "git_ssh", "sentry_token"]
396
-
397
- # Optional: cron schedule (standard cron syntax)
398
- # Agent must have at least one of: schedule, webhooks
399
- schedule = "*/5 * * * *"
400
-
401
- # Optional: number of concurrent runs allowed (default: 1)
402
- # When scale > 1, use lock skills in your actions to coordinate
403
- scale = 2
404
-
405
- # Optional: max runtime in seconds (default: falls back to [local].timeout, then 900)
406
- timeout = 600
407
-
408
- # Optional: webhook triggers (instead of or in addition to schedule)
409
- [[webhooks]]
410
- source = "my-github"
411
- repos = ["acme/app"]
412
- events = ["issues"]
413
- actions = ["labeled"]
414
- labels = ["agent"]
415
-
416
- [[webhooks]]
417
- source = "my-sentry"
418
- resources = ["error", "event_alert"]
419
-
420
- [[webhooks]]
421
- source = "my-linear"
422
- events = ["issues"]
423
- actions = ["create", "update"]
424
- labels = ["bug"]
425
-
426
- [[webhooks]]
427
- source = "my-mintlify"
428
- events = ["build"]
429
- actions = ["failed"]
430
-
431
- # Optional: hooks — shell commands that run before or after the LLM session
432
- [hooks]
433
- pre = [
434
- "gh repo clone acme/app /tmp/repo --depth 1",
435
- "curl -o /tmp/flags.json https://api.internal/v1/flags",
436
- ]
437
- post = ["upload-artifacts.sh"]
438
-
439
- # Optional: custom parameters injected into the agent prompt as <agent-config>
440
- [params]
441
- repos = ["acme/app", "acme/api"]
442
- triggerLabel = "agent"
443
- assignee = "bot-user"
444
- sentryOrg = "acme"
445
- sentryProjects = ["web-app", "api"]
446
- ```
447
-
448
- ### config.toml Field Reference
449
-
450
- | Field | Type | Required | Description |
451
- |-------|------|----------|-------------|
452
- | `source` | string | No | Git URL or GitHub shorthand for `al update`. Set automatically by `al add`. |
453
- | `models` | string[] | Yes | Named model references from `config.toml [models.*]`. First is primary; rest are fallbacks. |
454
- | `credentials` | string[] | Yes | Credential refs: `"type"` for default instance, `"type:instance"` for named instance. |
455
- | `schedule` | string | No* | Cron expression for polling |
456
- | `scale` | number | No | Number of concurrent runs allowed (default: 1). Set to `0` to disable the agent. |
457
- | `timeout` | number | No | Max runtime in seconds. Falls back to `[local].timeout` in project config, then `900`. |
458
- | `webhooks` | array | No* | Array of webhook trigger objects. |
459
- | `hooks` | table | No | Pre/post hooks that run around the LLM session. |
460
- | `params` | table | No | Custom key-value params injected into the prompt as `<agent-config>` |
461
-
462
- *At least one of `schedule` or `webhooks` is required (unless `scale = 0`).
463
-
464
- ### Scale
465
-
466
- Default: 1. Set 0 to disable. Busy: scheduled skipped, webhooks/calls queued.
467
-
468
- ### Timeout
469
-
470
- Max runtime per invocation. Container terminated with exit 124 on expiry.
471
-
472
- Resolves: agent -> project `[local].timeout` -> `900`.
473
-
474
- ### Hooks
475
-
476
- Shell commands that run before and after the LLM session, inside the container.
477
-
478
- **`hooks.pre`** — Run before context injection and LLM session. Use for cloning repos, fetching data, creating directories.
479
-
480
- **`hooks.post`** — Run after LLM session completes. Use for cleanup, artifact upload, reporting.
481
-
482
- Sequential execution. If a command fails (non-zero exit), the run aborts with error. Commands run via `/bin/sh -c "..."`.
483
-
484
- ```toml
485
- [hooks]
486
- pre = [
487
- "gh repo clone acme/app /tmp/repo --depth 1",
488
- "curl -o /tmp/flags.json https://api.internal/v1/flags",
489
- ]
490
- post = ["upload-artifacts.sh"]
491
- ```
492
-
493
- ### Webhook Trigger Fields
494
-
495
- Required `source` from `config.toml`. Filters optional (AND logic).
496
-
497
- | Field | Type | Required | Description |
498
- |-------|------|----------|-------------|
499
- | `source` | string | Yes | Name of a webhook source from the project's `config.toml` (e.g. `"my-github"`) |
500
-
501
- #### GitHub filter fields
502
-
503
- | Field | Type | Description |
504
- |-------|------|-------------|
505
- | `repos` | string[] | Filter to specific repos (owner/repo format) |
506
- | `orgs` | string[] | Filter to specific organizations |
507
- | `org` | string | Filter to a single organization |
508
- | `events` | string[] | Event types: issues, pull_request, push, issue_comment, workflow_run, etc. |
509
- | `actions` | string[] | Event actions: opened, labeled, closed, synchronize, etc. |
510
- | `labels` | string[] | Only trigger when issue/PR has these labels |
511
- | `assignee` | string | Only trigger when assigned to this user |
512
- | `author` | string | Only trigger for this author |
513
- | `branches` | string[] | Only trigger for these branches |
514
- | `conclusions` | string[] | Only for workflow_run events with these conclusions: success, failure, cancelled, skipped, timed_out, action_required |
515
-
516
- #### Sentry filter fields
517
-
518
- | Field | Type | Description |
519
- |-------|------|-------------|
520
- | `resources` | string[] | Resource types: event_alert, metric_alert, issue, error, comment |
521
-
522
- #### Linear filter fields
523
-
524
- | Field | Type | Description |
525
- |-------|------|-------------|
526
- | `organizations` | string[] | Filter to specific Linear organizations |
527
- | `events` | string[] | Linear event types: issues, issue_comment, etc. |
528
- | `actions` | string[] | Event actions: create, update, delete, etc. |
529
- | `labels` | string[] | Only when issue has these labels |
530
- | `assignee` | string | Only when assigned to this user (email) |
531
- | `author` | string | Only for this author (email) |
532
-
533
- #### Mintlify filter fields
534
-
535
- | Field | Type | Description |
536
- |-------|------|-------------|
537
- | `projects` | string[] | Filter to specific Mintlify projects |
538
- | `events` | string[] | Mintlify event types: build, etc. |
539
- | `actions` | string[] | Event actions: failed, succeeded, etc. |
540
- | `branches` | string[] | Only for these branches |
541
-
542
- ### Model Configuration
543
-
544
- Optional. If defined, fully overrides project default (no merging).
545
-
546
- ## Credentials
547
-
548
- Path: `~/.action-llama/credentials/<type>/<instance>/<field>`.
549
-
550
- **Agents MUST NEVER ask for credentials or run `al doctor`. Missing = report and stop.**
551
-
552
- ### How credentials work
553
-
554
- List in `agents/<name>/config.toml` credentials field. Mounted at `/credentials/...`, key values as env vars. `git_ssh` sets `GIT_AUTHOR_*`/`GIT_COMMITTER_*`. LLM creds auto-loaded from `[models.*]`.
555
-
556
- ### Agent runtime credentials
557
-
558
- | Type | Fields | Description | Runtime Injection |
559
- |------|--------|-------------|-------------------|
560
- | `github_token` | `token` | GitHub PAT with repo and workflow scopes | `GITHUB_TOKEN` and `GH_TOKEN` env vars |
561
- | `anthropic_key` | `token` | Anthropic API key, OAuth token, or pi auth | _(read by SDK)_ |
562
- | `openai_key` | `token` | OpenAI API key | _(read by SDK)_ |
563
- | `groq_key` | `token` | Groq API key | _(read by SDK)_ |
564
- | `google_key` | `token` | Google Gemini API key | _(read by SDK)_ |
565
- | `xai_key` | `token` | xAI API key | _(read by SDK)_ |
566
- | `mistral_key` | `token` | Mistral API key | _(read by SDK)_ |
567
- | `openrouter_key` | `token` | OpenRouter API key | _(read by SDK)_ |
568
- | `custom_key` | `token` | Custom provider API key | _(read by SDK)_ |
569
- | `sentry_token` | `token` | Sentry auth token for error monitoring | `SENTRY_AUTH_TOKEN` env var |
570
- | `linear_token` | `token` | Linear personal API token | `LINEAR_API_TOKEN` env var |
571
- | `linear_oauth` | `client_id`, `client_secret`, `access_token`, `refresh_token` | Linear OAuth2 credentials | `LINEAR_CLIENT_ID`, `LINEAR_CLIENT_SECRET`, `LINEAR_ACCESS_TOKEN`, `LINEAR_REFRESH_TOKEN` env vars |
572
- | `bugsnag_token` | `token` | Bugsnag auth token | `BUGSNAG_AUTH_TOKEN` env var |
573
- | `netlify_token` | `token` | Netlify Personal Access Token | `NETLIFY_AUTH_TOKEN` env var |
574
- | `mintlify_token` | `token` | Mintlify API token | `MINTLIFY_API_TOKEN` env var |
575
- | `git_ssh` | `id_rsa`, `username`, `email` | SSH private key + git author identity | SSH key mounted as file; `GIT_SSH_COMMAND` configured automatically; `GIT_AUTHOR_NAME`/`GIT_AUTHOR_EMAIL`/`GIT_COMMITTER_NAME`/`GIT_COMMITTER_EMAIL` set from `username`/`email` |
576
- | `x_twitter_api` | `api_key`, `api_secret`, `bearer_token`, `access_token`, `access_token_secret` | X (Twitter) API credentials | `X_API_KEY`, `X_API_SECRET`, `X_BEARER_TOKEN`, `X_ACCESS_TOKEN`, `X_ACCESS_TOKEN_SECRET` env vars |
577
- | `aws` | `access_key_id`, `secret_access_key`, `default_region` | AWS credentials | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_DEFAULT_REGION` env vars |
578
- | `reddit_oauth` | `client_id`, `client_secret`, `username`, `password`, `user_agent` | Reddit OAuth2 credentials for script apps | `REDDIT_CLIENT_ID`, `REDDIT_CLIENT_SECRET`, `REDDIT_USERNAME`, `REDDIT_PASSWORD`, `REDDIT_USER_AGENT` env vars |
579
-
580
- ### Webhook secrets
581
-
582
- | Type | Fields | Description |
583
- |------|--------|-------------|
584
- | `github_webhook_secret` | `secret` | Shared secret for GitHub webhook HMAC verification |
585
- | `sentry_client_secret` | `secret` | Client secret for Sentry webhook verification |
586
- | `linear_webhook_secret` | `secret` | Shared secret for Linear webhook verification |
587
- | `mintlify_webhook_secret` | `secret` | Shared secret for Mintlify webhook verification |
588
-
589
- Gateway only — not in agent containers.
590
-
591
- ### Infrastructure credentials
592
-
593
- CLI only (provisioning, deployment).
594
-
595
- | Type | Fields | Description |
596
- |------|--------|-------------|
597
- | `gateway_api_key` | `key` | API key for dashboard and CLI access to the gateway |
598
- | `vultr_api_key` | `api_key` | Vultr API key for VPS provisioning |
599
- | `hetzner_api_key` | `api_key` | Hetzner API key for VPS provisioning |
600
- | `cloudflare_api_token` | `token` | Cloudflare API token for DNS and TLS setup during provisioning |
601
- | `vps_ssh` | `id_rsa` | SSH private key for VPS access (generated or selected during provisioning) |
602
-
603
- ### Anthropic auth methods
604
-
605
- | `authType` | Token format | Description |
606
- |------------|-------------|-------------|
607
- | `api_key` | `sk-ant-api-...` | Standard Anthropic API key |
608
- | `oauth_token` | `sk-ant-oat-...` | OAuth token from `claude setup-token` |
609
- | `pi_auth` | _(none)_ | Uses existing pi auth credentials (`~/.pi/agent/auth.json`). No credential file needed. Not supported in Docker mode. |
610
-
611
- ## Models
612
-
613
- 8 providers. Define named models in `config.toml [models.*]`, reference by name in agent SKILL.md.
614
-
615
- | Provider | Credential | Example Models | Auth Types |
616
- |----------|-----------|---------------|------------|
617
- | `anthropic` | `anthropic_key` | `claude-opus-4-20250514`, `claude-sonnet-4-20250514`, `claude-haiku-3-5-20241022` | `api_key`, `oauth_token`, `pi_auth` |
618
- | `openai` | `openai_key` | `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo`, `o1-preview`, `o1-mini` | `api_key` |
619
- | `groq` | `groq_key` | `llama-3.3-70b-versatile` | `api_key` |
620
- | `google` | `google_key` | `gemini-2.0-flash-exp` | `api_key` |
621
- | `xai` | `xai_key` | `grok-beta` | `api_key` |
622
- | `mistral` | `mistral_key` | `mistral-large-2411` | `api_key` |
623
- | `openrouter` | `openrouter_key` | `anthropic/claude-3.5-sonnet` (provider/model format) | `api_key` |
624
- | `custom` | `custom_key` | _(any)_ | `api_key` |
625
-
626
- ### Thinking levels (Anthropic only)
627
-
628
- | Level | Description |
629
- |-------|-------------|
630
- | `off` | No extended thinking |
631
- | `minimal` | Minimal reasoning |
632
- | `low` | Light reasoning |
633
- | `medium` | Balanced (recommended) |
634
- | `high` | Deep reasoning |
635
- | `xhigh` | Maximum reasoning budget |
636
-
637
- Non-Anthropic providers ignore `thinkingLevel`.
638
-
639
- ## Webhooks
640
-
641
- Webhook triggers for agents.
642
-
643
- ### Runtime flow
644
-
645
- POST `/webhooks/<type>` -> verify -> match triggers (AND) -> trigger agent. Busy: queued.
646
-
647
- ## Agent Commands
648
-
649
- At `/app/bin/` (in `PATH`). Skill blocks teach usage.
650
-
651
- ### Signal commands
652
-
653
- Write signal files for scheduler.
654
-
655
- #### `al-rerun`
656
-
657
- Request immediate rerun to drain backlog.
658
-
659
- ```bash
660
- al-rerun
661
- ```
662
-
663
- Scheduled only. Until no `al-rerun`, error, or `maxReruns` (10).
664
-
665
- #### `al-status "<text>"`
666
-
667
- Update status text in TUI/dashboard.
668
-
669
- ```bash
670
- al-status "reviewing PR #42"
671
- al-status "found 3 issues to work on"
672
- ```
673
-
674
- #### `al-return "<value>"`
675
-
676
- Return a value to the calling agent (when invoked via `al-subagent`).
677
-
678
- ```bash
679
- al-return "PR looks good. Approved with minor suggestions."
680
- al-return '{"approved": true, "comments": 2}'
681
- ```
682
-
683
- For multiline, pipe via stdin:
684
-
685
- ```bash
686
- echo "Line 1\nLine 2" | al-return
687
- ```
688
-
689
- #### `al-exit [code]`
690
-
691
- Terminate with exit code (default: 15).
692
-
693
- ```bash
694
- al-exit # exit code 15
695
- al-exit 1 # exit code 1
696
- ```
697
-
698
- Codes: 10=auth, 11=perm, 12=rate, 13=config, 14=dep, 15=unrecoverable, 16=abort.
699
-
700
- ### Call commands
701
-
702
- Require gateway.
703
-
704
- #### `al-subagent <agent>`
705
-
706
- Call another agent. Pass context via stdin.
707
-
708
- ```bash
709
- echo "Review PR #42 on acme/app" | al-subagent reviewer
710
- ```
711
-
712
- ```json
713
- {"ok": true, "callId": "abc123"}
714
- {"ok": false, "error": "self-call not allowed"}
715
- {"ok": false, "error": "queue full"}
716
- ```
717
-
718
- #### `al-subagent-check <callId>`
719
-
720
- Non-blocking status check.
721
-
722
- ```bash
723
- al-subagent-check abc123
724
- ```
725
-
726
- ```json
727
- {"status": "pending"}
728
- {"status": "completed", "returnValue": "PR approved."}
729
- {"status": "error", "error": "timeout"}
730
- ```
731
-
732
- #### `al-subagent-wait <callId> [...] [--timeout N]`
733
-
734
- Wait for calls. Polls every 5s. Default timeout: 900s.
735
-
736
- ```bash
737
- al-subagent-wait abc123 --timeout 600
738
- al-subagent-wait abc123 def456 --timeout 300
739
- ```
740
-
741
- ```json
742
- {
743
- "abc123": {"status": "completed", "returnValue": "PR approved."},
744
- "def456": {"status": "completed", "returnValue": "Tests pass."}
745
- }
746
- ```
747
-
748
- #### Complete call example
749
-
750
- ```bash
751
- # Fire multiple calls
752
- REVIEW_ID=$(echo "Review PR #42 on acme/app" | al-subagent reviewer | jq -r .callId)
753
- TEST_ID=$(echo "Run full test suite for acme/app" | al-subagent tester | jq -r .callId)
754
-
755
- # ... do other work ...
756
-
757
- # Collect results
758
- RESULTS=$(al-subagent-wait "$REVIEW_ID" "$TEST_ID" --timeout 600)
759
- echo "$RESULTS" | jq ".\"$REVIEW_ID\".returnValue"
760
- echo "$RESULTS" | jq ".\"$TEST_ID\".returnValue"
761
- ```
762
-
763
- #### Call rules
764
-
765
- No self-calls. Chains up to `maxCallDepth` (3). Use `al-return` to respond.
766
-
767
- ### Lock commands
768
-
769
- Prevent duplicate work across instances.
770
-
771
- #### `rlock`
772
-
773
- Acquire exclusive lock.
774
-
775
- ```bash
776
- rlock "github://acme/app/issues/42"
777
- ```
778
-
779
- Responses:
780
-
781
- ```json
782
- {"ok": true}
783
- {"ok": false, "holder": "dev-abc123", "heldSince": "2025-01-15T10:30:00Z"}
784
- {"ok": false, "reason": "already holding lock on ..."}
785
- {"ok": false, "reason": "possible deadlock detected", "cycle": ["dev-abc", "github://acme/app/issues/10", "dev-def", "file:///deployments/api-prod"]}
786
- ```
787
-
788
- #### `runlock`
789
-
790
- Release a lock (holder only).
791
-
792
- ```bash
793
- runlock "github://acme/app/issues/42"
794
- ```
795
-
796
- ```json
797
- {"ok": true}
798
- {"ok": false, "reason": "not the lock holder"}
799
- ```
800
-
801
- #### `rlock-heartbeat`
802
-
803
- Reset TTL on held lock during long work.
804
-
805
- ```bash
806
- rlock-heartbeat "github://acme/app/issues/42"
807
- ```
808
-
809
- ```json
810
- {"ok": true, "expiresAt": "2025-01-15T11:00:00Z"}
811
- ```
812
-
813
- #### Lock behavior
814
-
815
- Per-run secret auth. Auto-release on exit. **One at a time**. Expire after `resourceLockTimeout` (1800s).
816
-
817
- #### Lock graceful degradation
818
-
819
- No gateway: locks degrade gracefully (exit 0). Calls exit 5.
820
-
821
- ## CLI Commands
822
-
823
- ### `al new <name>` — Create project
824
-
825
- ### `al doctor` — Check/prompt for missing credentials. `-E` pushes to server.
826
-
827
- ### `al run <agent>` — Single run for testing (`-H` headless)
828
-
829
- ### `al start` — Start scheduler (`-w` dashboard, `-e` expose, `-H` headless, `--port <N>`)
830
-
831
- ### `al stop` — Stop scheduler (in-flight runs finish)
832
-
833
- ### `al stat` — Agent status overview
834
-
835
- ### `al logs <agent>` — View logs (`-n`, `-f`, `-d`, `-r`, `-i`)
836
-
837
- ### `al pause/resume [name]` — Pause/resume scheduler or agent
838
-
839
- ### `al kill <target>` — Kill agent or instance
840
-
841
- ### `al chat [agent]` — Interactive console (with agent: credentials injected)
842
-
843
- ### `al push [agent]` — Deploy via SSH (full or hot-reload single agent)
844
-
845
- `--dry-run`, `--no-creds`, `--creds-only`, `--files-only`, `-a`, `--force-install`.
846
-
847
- ### Environment commands
848
-
849
- #### `al env init <name>` — Create at `~/.action-llama/environments/<name>.toml`
850
-
851
- #### `al env list` / `al env show <name>` — List or show environments
852
-
853
- #### `al env set [name]` — Bind/unbind project to environment (`.env.toml`)
854
-
855
- #### `al env check <name>` — Verify SSH, Docker, server readiness
856
-
857
- #### `al env prov [name]` — Provision VPS (Vultr/Hetzner)
858
-
859
- #### `al env deprov <name>` — Tear down environment
860
-
861
- #### `al env logs [name]` — Server logs via SSH (`-n`, `-f`)
862
-
863
- ### Credential commands
864
-
865
- #### `al creds ls` — List credentials (names, not values)
866
-
867
- #### `al creds add <ref>` — Add/update (`github_token` or `git_ssh:prod`)
868
-
869
- #### `al creds rm <ref>` — Remove credential
870
-
871
- #### `al creds types` — Browse credential types
872
-
873
- ### Agent commands
874
-
875
- #### `al agent new` — Create from template (dev, reviewer, devops, custom)
876
-
877
- #### `al agent config <name>` — Configure agent interactively
878
-
879
- ### Global options
880
-
881
- `-p <dir>` (project, default `.`) and `-E <name>` (env, also `AL_ENV` or `.env.toml`).
882
-
883
- ## Docker
884
-
885
- ### Image build order
886
-
887
- ```
888
- al-agent:latest ← Action Llama package (automatic, built on first run)
889
-
890
- al-project-base:latest ← project Dockerfile (skipped if unmodified from bare FROM)
891
-
892
- al-<agent>:latest ← per-agent Dockerfile (if present)
893
- ```
894
-
895
- Bare project Dockerfile skips middle layer.
896
-
897
- ### Base image contents
898
-
899
- Built from `node:20-alpine`:
900
-
901
- | Package | Purpose |
902
- |---------|---------|
903
- | `node:20-alpine` | Container entry point, pi-coding-agent SDK |
904
- | `git` | Clone repos, create branches, push commits |
905
- | `curl` | API calls (Sentry, arbitrary HTTP), anti-exfiltration shutdown |
906
- | `jq` | JSON processing in bash |
907
- | `ca-certificates` | HTTPS for git, curl, npm |
908
- | `openssh-client` | SSH for `GIT_SSH_COMMAND` — git clone/push over SSH |
909
-
910
- Entry: `node /app/dist/agents/container-entry.js`. Commands at `/app/bin/`.
911
-
912
- ### Dockerfile conventions
913
-
914
- `FROM al-agent:latest` (auto-rewritten). Images: `al-<name>:latest`.
915
-
916
- #### Project Dockerfile example
917
-
918
- ```dockerfile
919
- FROM al-agent:latest
920
-
921
- # Install tools shared by all agents
922
- RUN apk add --no-cache python3 py3-pip github-cli
923
-
924
- # Set shared environment variables
925
- ENV MY_ORG=acme
926
- ```
927
-
928
- #### Per-agent Dockerfile example
929
-
930
- ```dockerfile
931
- FROM al-agent:latest
932
-
933
- USER root
934
- RUN apk add --no-cache github-cli
935
- USER node
936
- ```
937
-
938
- #### Standalone Dockerfile (full control)
939
-
940
- Needs Node.js 20+, entry.js, `USER node`.
941
-
942
- ```dockerfile
943
- FROM node:20-alpine
944
-
945
- RUN apk add --no-cache git curl ca-certificates openssh-client github-cli jq python3
946
-
947
- COPY --from=al-agent:latest /app /app
948
- WORKDIR /app
949
-
950
- USER node
951
- ENTRYPOINT ["node", "/app/dist/agents/container-entry.js"]
952
- ```
953
-
954
- Reads `AGENT_CONFIG`, `PROMPT`, `GATEWAY_URL` from env.
955
-
956
- ### Container filesystem
957
-
958
- Read-only root, non-root user, resource limits.
959
-
960
- | Path | Mode | Contents |
961
- |------|------|----------|
962
- | `/app` | read-only | Action Llama application + node_modules |
963
- | `/app/static` | read-only | Agent files baked at build time (SKILL.md, agent-config.json, prompt skeleton) |
964
- | `/app/bin` | read-only | Shell commands (al-rerun, al-status, rlock, etc.) — added to PATH at startup |
965
- | `/credentials` | read-only | Mounted credential files (`/<type>/<instance>/<field>`) |
966
- | `/tmp` | read-write (tmpfs, 2GB) | Agent working directory — repos, scratch files, SSH keys |
967
- | `/workspace` | read-write (2GB) | Persistent workspace |
968
- | `/home/node` | read-write (64MB) | Home directory |
969
-
970
- ### Environment variable persistence
971
-
972
- Use `setenv` to persist environment variables across bash commands:
973
-
974
- ```bash
975
- setenv REPO "owner/repo"
976
- setenv ISSUE_NUMBER 42
977
- gh issue view $ISSUE_NUMBER --repo $REPO
978
- ```
979
-
980
- See `[local]` in config.toml for Docker configuration options.
981
-
982
- ## Gateway API
983
-
984
- Auto-starting HTTP server. Port: `[gateway].port`.
985
-
986
- API key at `~/.action-llama/credentials/gateway_api_key/default/key`.
987
-
988
- ### Protected routes
989
-
990
- | Route | Auth |
991
- |-------|------|
992
- | `/dashboard` and `/dashboard/*` | Required |
993
- | `/control/*` | Required |
994
- | `/locks/status` | Required |
995
- | `/health` | None |
996
- | `/webhooks/*` | None (HMAC validation per-source) |
997
-
998
- ### Control API
999
-
1000
- All `POST`, require auth.
1001
-
1002
- **Scheduler:**
1003
-
1004
- | Endpoint | Description |
1005
- |----------|-------------|
1006
- | `POST /control/pause` | Pause the scheduler (all cron jobs) |
1007
- | `POST /control/resume` | Resume the scheduler |
1008
-
1009
- **Agents:**
1010
-
1011
- | Endpoint | Description |
1012
- |----------|-------------|
1013
- | `POST /control/trigger/<name>` | Trigger an immediate agent run |
1014
- | `POST /control/agents/<name>/enable` | Enable a disabled agent |
1015
- | `POST /control/agents/<name>/disable` | Disable an agent (pauses its cron job) |
1016
- | `POST /control/agents/<name>/pause` | Pause an agent (alias for disable) |
1017
- | `POST /control/agents/<name>/resume` | Resume an agent (alias for enable) |
1018
- | `POST /control/agents/<name>/kill` | Kill all running instances of an agent |
1019
-
1020
- ### SSE Streams
1021
-
1022
- Live updates via **SSE**:
1023
-
1024
- | Endpoint | Description |
1025
- |----------|-------------|
1026
- | `GET /dashboard/api/status-stream` | Pushes agent status and scheduler info whenever state changes |
1027
- | `GET /dashboard/api/logs/<agent>/stream` | Streams log lines for a specific agent (500ms poll interval) |
1028
-
1029
- ### Other endpoints
1030
-
1031
- | Endpoint | Method | Auth | Description |
1032
- |----------|--------|------|-------------|
1033
- | `GET /health` | GET | No | Health check (no authentication required) |
1034
- | `GET /locks/status` | GET | Yes | Active resource lock information |
1035
-
1036
- ## Web Dashboard
1037
-
1038
- Enable with `al start -w`. URL: `http://localhost:<port>/dashboard`. Login with gateway API key.
1039
-
1040
- ### `/dashboard`
1041
-
1042
- | Column | Description |
1043
- |--------|-------------|
1044
- | Agent | Agent name (click to view logs) |
1045
- | State | Current state: idle, running, building, or error |
1046
- | Status | Latest status text or error message |
1047
- | Last Run | Timestamp of the most recent run |
1048
- | Duration | How long the last run took |
1049
- | Next Run | When the next scheduled run will happen |
1050
- | Actions | **Run** (trigger an immediate run) and **Enable/Disable** (toggle the agent) |
1051
-
1052
- Pause/Resume, Recent Activity. SSE updates.
1053
-
1054
- ### `/dashboard/agents/<name>/logs` — Live streaming agent logs
1055
-
1056
- ## Environments
1057
-
1058
- Three-layer config merge (later wins):
1059
-
1060
- | Layer | File | Scope | Contents |
1061
- |-------|------|-------|----------|
1062
- | 1 | `config.toml` | Project (committed) | `[models.*]`, `[local]`, `[gateway]`, `[webhooks]`, `[telemetry]`, top-level scheduler fields |
1063
- | 2 | `.env.toml` | Project (gitignored) | `environment` field to select env, can override any config value |
1064
- | 3 | `~/.action-llama/environments/<name>.toml` | Machine | `[server]` (SSH push deploy), `gateway.url`, `telemetry.endpoint` |
1065
-
1066
- `[cloud]`/`[server]` must be Layer 3. Mutually exclusive.
1067
-
1068
- Priority: `-E` flag > `AL_ENV` env var > `.env.toml`. Type: `server`.
1069
-
1070
- ### Server environment example
1071
-
1072
- ```toml
1073
- # ~/.action-llama/environments/production.toml
1074
- [server]
1075
- host = "5.6.7.8"
1076
- user = "root"
1077
- keyPath = "~/.ssh/id_rsa"
1078
- basePath = "/opt/action-llama"
1079
- expose = true
1080
- ```
1081
-
1082
- ### VPS credential sync
1083
-
1084
- Credentials synced via SSH.
1085
-
1086
- ## Running Agents
1087
-
1088
- `al start` runs all agents. No per-agent start.
1089
-
1090
- ### Automatic re-runs
1091
-
1092
- `al-rerun` triggers re-run until done/error/`maxReruns`. Webhook/call runs don't re-run.
1093
-
1094
- ## Exit Codes
1095
-
1096
- ### Shell command exit codes
1097
-
1098
- **Always check exit codes.**
1099
-
1100
- | Exit | Meaning | HTTP | When |
1101
- |------|---------|------|------|
1102
- | 0 | Success | 200 | Operation completed |
1103
- | 1 | Conflict | 409 | Resource held by another, deadlock detected, or dispatch rejected |
1104
- | 2 | Not found | 404 | Resource or call doesn't exist |
1105
- | 3 | Auth error | 403 | Invalid or expired secret |
1106
- | 4 | Bad request | 400 | Server rejected the request (malformed payload) |
1107
- | 5 | Unavailable | 503 | Service not ready, no gateway configured |
1108
- | 6 | Unreachable | — | Gateway connection failed |
1109
- | 7 | Unexpected | other | Unknown HTTP status |
1110
- | 8 | Timeout | — | `al-subagent-wait` only: polling deadline exceeded |
1111
- | 9 | Usage error | — | Missing argument (local check, never hits network) |
1112
- | 10 | Bad gateway | 502 | Proxy could not reach the gateway |
1113
- | 11 | Gateway timeout | 504 | Proxy timed out reaching the gateway |
1114
- | 12 | Server error | 500 | Internal gateway error |
1115
-
1116
- ### Agent exit codes (`al-exit`)
1117
-
1118
- | Exit | Meaning |
1119
- |------|---------|
1120
- | 10 | Auth failure |
1121
- | 11 | Permission denied |
1122
- | 12 | Rate limited |
1123
- | 13 | Config error |
1124
- | 14 | Dependency error |
1125
- | 15 | Unrecoverable (default) |
1126
- | 16 | User abort |
1127
-
1128
- Timeout: exit 124.