~/.pylon/pylons/<name>/pylon.yaml. Running pylon construct <name> creates this file through an interactive prompt; you can open it in your editor at any time with pylon edit <name>. Per-pylon settings take priority over the global defaults in ~/.pylon/config.yaml, so you only need to specify fields that differ from the global configuration.
Examples
These are complete, copy-pasteablepylon.yaml files covering the three most common patterns.
Sentry webhook with approval
A webhook pylon that triages Sentry errors. HMAC validation ensures only authentic Sentry payloads are accepted, andapproval: true requires a human to approve each job before the agent starts.
GitHub PR review (no approval)
A webhook pylon that reviews every pull request automatically. The workspace repo and branch are resolved dynamically from the GitHub webhook payload, so the agent always clones the exact branch under review. No approval step — the agent starts immediately.Cron audit (scheduled weekly)
A cron pylon that runs a weekly security audit. There is no webhook trigger — Pylon fires the job on a schedule. The workspace is a fresh git clone so the agent always audits the latest code.Field reference
Top-level fields
Identifier for this pylon. Must match the directory name under
~/.pylon/pylons/. Set automatically by pylon construct.Optional human-readable description shown in
pylon list output.When
true, pylon start skips this pylon entirely. Use this to temporarily pause a pylon without deleting it.ISO 8601 timestamp set automatically when you run
pylon construct. Do not edit this field.trigger
How the pylon is activated. Accepted values:
webhook, cron.URL path for the webhook endpoint (for example,
/my-pipeline). Required when type is webhook. Pylon registers this path on the global server port when the daemon starts.Cron expression for scheduled pylons (for example,
0 9 * * 1-5 for weekdays at 9 AM). Required when type is cron.HMAC secret used to validate incoming webhook signatures. When set, Pylon rejects requests whose signature does not match. Use
${VAR} to reference a value from ~/.pylon/.env.HTTP header Pylon reads to find the HMAC signature (for example,
X-Hub-Signature-256). Required when trigger.secret is set.Overrides
server.public_url from the global config for this pylon only. Useful when a single Pylon server serves webhooks from multiple domains.workspace
How the agent accesses source code. Accepted values:
git-clone— Pylon clones the repository fresh for each job.git-worktree— Pylon creates a worktree from a local clone, which is faster than a full clone.local— Pylon mounts a local directory from the host into the container.none— No codebase. Use this for pylons that do not need to read or modify files.
Git repository URL. Use SSH (
git@github.com:org/repo.git) for private repositories. Supports template variables so you can resolve the URL from the webhook payload (for example, {{ .body.repository.clone_url }}). Required when type is git-clone or git-worktree.Branch or tag to check out. Supports template variables (for example,
{{ .body.pull_request.head.ref }}). Defaults to main when not specified.Absolute path to a local directory on the host. Pylon mounts this directory into the agent container. Required when
type is local.channel
The channel block is optional. When omitted, the pylon uses the global defaults.channel from config.yaml. When present, the pylon-level settings take full priority.
Notification backend for this pylon. Accepted values:
telegram, slack, webhook, stdout. Overrides the global default.Telegram connection settings. Accepts the same fields as
defaults.channel.telegram in the global config. Required when channel.type is telegram.Slack connection settings. Accepts the same fields as
defaults.channel.slack in the global config. Required when channel.type is slack.Thread or topic subject line shown in the notification. Supports template variables for injecting webhook payload data.
Notification message body displayed above the Approve/Ignore buttons. Supports template variables.
When
true, Pylon sends a notification with Approve and Ignore buttons and waits for a human to respond before starting the agent. When false, the agent starts immediately on every trigger event.agent
The agent block is optional. When omitted, the pylon uses defaults.agent from the global config.
Agent runtime for this pylon. Accepted values:
claude, opencode. Overrides the global default.Authentication method. Overrides the global default for the chosen agent type. Accepted values:
oauth, api_key (Claude); none, api-key (OpenCode).API key reference, used when
auth is api_key. Use ${VAR} to reference a value from ~/.pylon/.env (for example, ${ANTHROPIC_API_KEY}). This lets you assign a different key per pylon.LLM provider for OpenCode agents. Accepted values:
anthropic, openai, google. Overrides the global default.Additional environment variables injected into the agent container. Use this to pass service-specific configuration without hardcoding values in the prompt.
The instruction sent to the agent when a job starts. Supports Go template syntax to inject data from the webhook payload. See the Prompt templates section below.
Maximum run time for a single job (for example,
10m, 30m). Overrides docker.default_timeout from the global config.Host CLI tools available to this pylon’s agent. When set, this list replaces the global
tools list entirely for this pylon. Each entry accepts name, path, and an optional timeout. See the Host tools section below.Prompt templates
Pylon renders your agent prompt as a Go template before sending it to the agent container. This means you can embed data from the incoming webhook payload directly in the prompt, so the agent receives context-rich instructions without any extra glue code. The same template syntax works inchannel.topic and channel.message, letting you surface the right information in your notification thread title and preview message.
Template syntax
Access a field from the webhook JSON body using double curly braces and the.body prefix:
text/template package. Any valid Go template expression works, including conditionals and range loops, but most prompts only need simple field substitutions.
Available variables
| Variable | Description |
|---|---|
{{ .body.error }} | Generic top-level error message |
{{ .body.issue.title }} | Issue title (GitHub, Linear, or generic) |
{{ .body.number }} | Pull request or issue number |
{{ .body.pull_request.title }} | GitHub pull request title |
{{ .body.pull_request.head.ref }} | Branch name for a pull request |
{{ .body.repository.clone_url }} | HTTPS clone URL for the repository |
{{ .body.data.event.title }} | Sentry event title |
{{ .body.data.event.culprit }} | Sentry culprit file and function |
{{ .body.data.event.level }} | Sentry severity level (e.g. error, fatal) |
{{ .body.data.event.platform }} | Sentry platform (e.g. python, javascript) |
{{ .body.data.event.web_url }} | Link to the Sentry issue in the web UI |
Template examples
Sentry error triage — inject event details from a Sentry webhook:workspace.repo and workspace.ref, so Pylon clones the exact branch being reviewed.
Notification channel fields — template variables apply to channel.topic and channel.message too, not just the agent prompt:
Testing template expansion
Usepylon test with a --payload flag to see how your templates expand against a sample payload before sending real traffic:
Tips
Host tools
By default, agent containers are isolated Docker environments with no access to your host filesystem or binaries. Host tools let you selectively expose specific CLI programs — deployment scripts, linters, build tools — to agents via Pylon’s exec gateway. The gateway proxies calls from inside the container to named executables on the host, so agents can trigger real workflows without needing a privileged container or a shared filesystem mount.Configuring tools per pylon
Theagent.tools list in pylon.yaml controls which host tools this pylon’s agent can call. Each entry defines one tool:
Identifier used to reference this tool in agent instructions. Choose a short, descriptive name without spaces.
Absolute path to the executable on the host machine. The file must be executable by the user running
pylon start.Maximum time Pylon waits for a single tool invocation to complete. Accepts Go duration strings such as
30s, 2m. If the tool does not finish within this limit, Pylon terminates the call and returns an error to the agent.Resolution order
Ifagent.tools is set (even to an empty list), it replaces the global tools list from config.yaml for that pylon. If agent.tools is absent, Pylon uses the global list. This means you can give individual pylons a restricted subset of tools, or grant a specific pylon access to a tool not available globally.
Security model
Agents cannot run arbitrary commands on your host. They can only call tools by name through the exec gateway, and only tools that appear in the pylon’s resolved tools list are reachable. If an agent attempts to call a tool that is not listed, the gateway rejects the call.Example: deploy script
A common pattern is exposing a deployment script that agents can invoke after making code changes:/usr/local/bin/deploy.sh on the host, captures its output, and returns it to the agent.
Config resolution order
When Pylon runs a job it merges settings from both files, with the per-pylon file taking full priority:| Setting | Resolved from |
|---|---|
channel.type | Per-pylon channel.type -> global defaults.channel.type |
agent.type | Per-pylon agent.type -> global defaults.agent.type -> claude |
agent.auth | Per-pylon agent.auth -> global agent defaults -> oauth (Claude) |
agent.timeout | Per-pylon agent.timeout -> global docker.default_timeout -> 15m |
agent.tools | Per-pylon agent.tools (if non-empty) -> global tools |