hub.yml reference
A configuration has environments and triggers. It may also include top-level project deployment metadata for paseo hub deploy. Execution fields belong to each trigger's steps.
project: my-project
environments:
- name: development
kind: daemon
daemon: my-macbook
cwd: /Users/you/code/project
triggers:
- name: request
on: manual.run
max_runtime: 2h
filters:
from_users: [automation]
steps:
- id: work
environment: development
max_runtime: 90m
idle_timeout: 10m
agent:
provider: codex
mode: full-access
prompt:
- text: Call hub.finish_execution when the step is complete.
- text: |
<user-prompt>
${{ paseo.prompt }}
</user-prompt>
project is an optional bare project slug. The deploy CLI uses it to choose the target project when -p, --project is absent. The flag takes precedence over this metadata without rewriting the YAML. project is not available to triggers, expressions, or agents.
Environments
| Field | Required | Notes |
|---|---|---|
name | yes | Lowercase identifier referenced by a step. |
kind | yes | daemon, fly, or docker in the authored schema; workflow steps must resolve to a daemon environment. |
daemon | daemon only | Friendly daemon slug, resolved to its immutable ID when the revision activates. |
cwd | daemon only | Absolute path on the daemon. |
image | fly/docker | Image name. |
worktree | no | branch-off, checkout-branch, or checkout-pr target. |
The worktree object is part of the environment. Its fields are exact authored names: newBranch and optional base for branch-off, branch for checkout-branch, and positive integer prNumber for checkout-pr. Give base a remote-tracking ref such as origin/main; see Git worktrees.
Triggers
| Field | Required | Notes |
|---|---|---|
name | yes | Lowercase identifier, unique in the configuration. |
on | yes | provider.event, such as slack.mention or manual.run. |
max_runtime | yes | Positive duration for the complete trigger run, up to 24h. |
filters | no in schema | Provider filters; externally sourced triggers still require a non-empty from_users allowlist. |
inputs | no | Typed leading key=value invocation headers. |
values | no | Derived expressions. |
steps | yes | One or more ordered steps. |
Inputs
Each input has:
inputs:
repo:
type: string
required: false
choices: [project, paseo]
agent:
type: string
default: codex
choices: [codex, claude]
type is string, number, or boolean. required, default, and choices are optional. required and default cannot be combined. Defaults and choices must match the declared type; a default must be one of the choices.
Inputs may be referenced as ${{ paseo.inputs.name }}. A dynamic authority-bearing field such as a provider, model, mode, or environment requires finite choices at activation. A prompt cannot supply authority.
Values
Values bind expressions under their own namespace:
values:
selected_repo: ${{ paseo.inputs.repo ?? steps.classify.outputs.repo }}
The grammar supports paths, JSON literals, parentheses, !, ==, !=, &&, ||, and ??. It does not support function calls, JavaScript, arithmetic, mutation, or implicit string coercion. Referenced steps must exist and value dependencies cannot cycle.
Steps
| Field | Required | Notes |
|---|---|---|
id | yes | Lowercase step identifier, unique within the trigger. |
environment | yes | Environment name or a finite input expression resolving to one. |
max_runtime | yes | Positive step hard limit, up to 24h. |
idle_timeout | yes | Positive idle limit, no longer than the step hard limit. |
agent | yes | provider, optional model, mode, thinkingOptionId, and provider-native options. |
prompt | yes | Non-empty list of text and GitHub-only include blocks. |
if | no | Expression deciding whether this ordered step runs. |
env | no | Environment variables populated from connection values. See GitHub access. |
output | no | { schema: <JSON Schema> } for the structured result the agent passes to hub.finish_execution. |
allow_outputs | no | Registered output capabilities such as slack.reply or discord.reply, each with optional max and required. |
auto_archive | no | Archives the step's agent when it ends. |
github | no | Scoped GitHub token and git setup for this step. See GitHub access. |
Prompt blocks are objects, not a scalar prompt:
prompt:
- include: developer.md
- text: |
<user-prompt>
${{ paseo.prompt }}
</user-prompt>
Keep the triggering message in its own final block, wrapped in <user-prompt> tags, as the first workflow does.
Use ${{ paseo.prompt }}, ${{ paseo.inputs.* }}, ${{ steps.*.outputs.* }}, and ${{ values.* }} in prompts, conditions, and agent selection fields. Provider event payloads are not part of this workflow expression namespace; provider adapters put the normalized request into the prompt and preserve the raw event as evidence.
agent.options carries JSON-safe options using the selected provider's native names and nesting. Paseo validates them with that provider's strict schema before starting the session. See Hub security for the trust boundary and copyable provider examples.
mode names a Paseo agent mode ID, which is a separate surface from these options. Some modes keep the provider's interactive approval flow, and that stalls an unattended step, so set the provider's own approval and sandbox settings in options instead.
Output capabilities
allow_outputs separates permission from obligation. max limits how many times a capability may be emitted and defaults to 1. Set required: true when the step must emit that capability at least once before it can finish successfully:
allow_outputs:
- type: discord.reply
max: 1
required: true
required: true means the step must actually emit the capability. Assistant text does not count.
- A required output must resolve to a registered, available capability for the execution, or dispatch rejects the step.
- A required output needs an effective
maxof at least1, or activation rejects the configuration. - Failed delivery is retryable. An agent that tries to finish first is told the concrete output tool to call, then
hub.finish_executionis retried.
Omitting required keeps the output optional. GitHub has no reply capability; a step acts through the gh CLI with the token its github block grants.
A declaration grants the tool. The step's prompt still has to tell the agent to call hub.reply, and to call hub.finish_execution when it is done. See Tell the agent which tool to call.
Prompt partials
include paths are relative to .paseo/partials/.
- GitHub configuration: Hub reads each file at the exact configuration commit and stores the resolved content and SHA-256 hash in the immutable revision.
paseo hub deploy: the CLI reads the referenced files from the local project root and sends them in the optionalpartialsbundle. The bundle path omits the.paseo/partials/prefix.- Missing files, unsafe paths, symlinks, submodules, directories, duplicate or unexpected bundle entries, and nested includes are rejected.
- Manual configurations cannot use repository partials.
Deadlines
The trigger's max_runtime is the hard limit for the complete workflow run. Each step also has max_runtime and idle_timeout:
max_runtime: 2h
steps:
- id: classify
max_runtime: 2m
idle_timeout: 30s
- id: implement
max_runtime: 90m
idle_timeout: 10m
The effective step hard and idle deadlines are capped by the remaining trigger deadline. Meaningful daemon activity refreshes idle time, but cannot extend a hard deadline. Hub persists absolute deadlines, so a restart or deployment does not reset them. A step timeout fails the run; a trigger timeout stops later steps and interrupts a live agent.
Provider invocation
The provider removes its mention or marker before Hub parses leading declared input tokens. Slack and Discord place the inputs immediately after the bot mention. GitHub places them after the configured marker. Manual runs send the same string as the API input:
@Paseo repo=project investigate the failed sync
The first token that is not a declared input begins the prompt. The clean prompt is available as ${{ paseo.prompt }}. The raw provider message remains separate Activity evidence. See provider triggers for provider-specific marker and filter behavior.
Removed fields
Do not put execution fields directly on a trigger. environment, agent, prompt, timeout, idle_timeout, auto_archive, and allow_outputs are step fields now. The duration field is max_runtime; timeout is not an alias.
Next: Hub workflows for routing patterns and copyable configurations.