Guardrails for agent automation
Letting an agent run your deploy procedure doesn't mean letting it run wild. Dry-run to preview, validate to catch missing variables, a prompt to require a human yes, and secrets that never land in the transcript.
The pitch for agent automation is that the agent runs your procedures for you. The fear — the reasonable, do-not-ignore-it fear — is that it runs the wrong one, against the wrong target, with a variable it silently left empty, and leaks a token into a chat log on the way.
You don't address that fear by trusting the agent more. You address it by giving it a procedure that's hard to misuse: previewable before it runs, checkable for missing inputs, gated by a human on the steps that matter, and built so secrets never surface in output the agent can see. OrchStep gives you all four as plain features of a workflow.
The workflow, built to be driven safely
name: agent-deploy
# Built to be safe for an agent to drive: every run is previewable,
# variable references are checkable, and the publish step needs a human yes.
defaults:
service: payments
target: staging
tasks:
ship:
steps:
- name: build
func: shell
do: echo "building {{ vars.service }} for {{ vars.target }}"
- name: approve
func: prompt
args:
message: "Let the agent ship {{ vars.service }} to {{ vars.target }}?"
type: confirm
default: false
- name: gate
if: '{{ eq steps.approve.value "true" }}'
then:
- name: publish
func: shell
do: echo "publishing {{ vars.service }} to {{ vars.target }}"
else:
- name: hold
func: shell
do: echo "approval denied; nothing shipped"Four guardrails are wired into how an agent would run this, not bolted on after.
Guardrail 1: preview before it runs
Before the agent executes anything, it can resolve the whole plan and execute nothing:
orchstep run ship --dry-runThe dry-run renders every variable, evaluates the if, and prints the exact sequence of steps. You — or a reviewer — see that target is staging, not production, before a single command runs. For an agent you're still building trust in, you can require the dry-run first and review the plan it produces. Full tour: Previewing with Dry Run.
Guardrail 2: catch the missing variable
The classic agent failure is a reference to a variable nothing supplies, which renders empty and ships a half-formed command. validate catches that statically, without running anything:
orchstep validate ship --strictIt walks the task's vars.* references and reports any that no layer supplies — defaults, env files, task or step vars, or --var. With --strict, an unresolved reference is a hard failure, so an agent's "I'll just leave that blank" never makes it to execution. See Validating Variables.
Guardrail 3: a human on the trigger
Some steps should never run on the agent's say-so alone. The prompt step is a hard stop:
- name: approve
func: prompt
args:
message: "Let the agent ship {{ vars.service }} to {{ vars.target }}?"
type: confirm
default: falseThe gate step only takes the publish branch when steps.approve.value is "true". The default: false matters: in a non-interactive context where no human answers, it resolves to the safe default and the workflow takes the hold branch. The agent can do everything up to the gate; it cannot walk through it unattended.
Guardrail 4: secrets the agent never sees
The fourth fear is leakage — a token printed into output the agent reads and then echoes back into a chat log. OrchStep's environment layer keeps credentials out of the workflow file and out of step output: declare them in environment config rather than inline, and reference them by name. Combined with --output json for the agent to read, the structured result carries step status and outputs you chose to expose — not the raw credential. Keep secrets in environment files (see Environments), never in defaults: or a do: string the agent can scrape.
The safe-by-default run order
| Stage | Command | What it guarantees |
|---|---|---|
| Plan | orchstep run ship --dry-run | nothing executes; the plan is reviewable |
| Inputs | orchstep validate ship --strict | no variable renders empty |
| Approval | func: prompt gate | a human confirms the real action |
| Secrets | environment config | credentials never hit step output |
None of this slows the agent down on the safe path — a dry-run and a validate are fast, and the prompt only blocks the one step that should block. What it removes is the failure mode where an agent confidently does the wrong, irreversible thing.
Where OrchStep is not the answer
If your concern is the agent reading or exfiltrating source, that's a sandboxing and permissions problem upstream of any workflow tool — solve it where the agent runs. OrchStep guards the actions a workflow takes, not the agent's filesystem access.
Where to go next
- LLM Agent Integration — how agents drive workflows
- Previewing with Dry Run — review the plan before it runs
- Environments — keep secrets out of the workflow file
- Variables & Outputs — validate references before running
Letting an agent touch a real environment? Wire the dry-run and the prompt gate in first — orchstep init gives you the shape.
curl -fsSL https://orchstep.dev/install.sh | sh