Reentrant Blessed Scripts
A reentrant Blessed Script is a workflow pattern built from an ordinary Blessing. The script performs deterministic work until it needs judgment, prints a prompt, and exits. An agent supplies the requested input and invokes a fixed entry point to continue.
Automic Vault evaluates each invocation against the same Script Declaration and makes a new Authorization Decision. An earlier invocation grants no authority to the next one. The Blessing also cannot carry shell state, environment variables, or open file descriptors across the gap.
Use reentry when a workflow needs bounded judgment, such as writing release notes, choosing among reviewed deployment targets, or classifying a failure. Keep a deterministic workflow in one invocation when no judgment is required.
Build a small state machine
Give the script a short list of entry points. Each entry point should accept a validated operation identifier such as a release version or deployment ID. Reject unknown actions and extra arguments.
SELF="${AV_SCRIPT_PATH:-$0}"
ACTION="${1:-continue}"
VERSION="${2:-}"
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || {
echo "usage: $SELF {continue|agent:github-context|agent:cdn-status} VERSION" >&2
exit 64
}
case "$ACTION" in
agent:github-context) github_context ;;
agent:cdn-status) cdn_status ;;
continue) continue_release ;;
*) echo "error: unknown action: $ACTION" >&2; exit 64 ;;
esac
Use AV_SCRIPT_PATH when the script prints its own
reentry command. Automic Vault sets it to the canonical source path
while executing the verified snapshot. $0 may point at
/dev/fd/N and will not provide a stable command for the
agent.
Every invocation starts a new process. Store required non-secret state in a protected run directory or recover it from the destination service. Do not rely on the previous shell process.
Return the prompt to the agent
Print the handoff prompt to standard output. An agent that invoked the script through a terminal receives that output in the command result, so the script does not need an agent-specific API or MCP server. Send diagnostics to standard error so a wrapper can distinguish them from the prompt.
Exit with a documented nonzero status after printing the prompt.
Status 75, EX_TEMPFAIL on macOS, tells a caller that the
operation paused before completion. An exit status of zero can cause a
parent task to report success and discard the pending handoff.
Long command output may be truncated. After creating and validating the protected run directory, save the same prompt there and print its path as the last line:
agent_prompt() {
umask 077
local prompt="$RUN_DIR/next.md" tmp
tmp="$(mktemp "$RUN_DIR/.next.XXXXXX")"
cat >"$tmp" <<EOF
Write concise release notes for $REPOSITORY $VERSION to:
$NOTES
For recent GitHub context, run:
"$SELF" agent:github-context "$VERSION"
For current CDN state, run:
"$SELF" agent:cdn-status "$VERSION"
Do not run gh or aws outside these entry points. Do not include Secret Values.
Resume with:
"$SELF" continue "$VERSION"
EOF
mv -f -- "$tmp" "$prompt"
cat "$prompt"
printf '\nPrompt saved at: %s\n' "$prompt"
exit 75
}
If a human launched the script, they can paste the printed block into the agent conversation. If the agent launched it, tell the agent in the initial prompt to treat status 75 and the script's output as the next task.
Craft the initial agent prompt
The initial prompt should establish the workflow boundary before the agent runs anything. Include:
- the goal and the exact first command;
- the working directory and immutable operation identifier;
- the rule that the Blessed Script owns gated Tools and Secret Use;
- the status-75 handoff protocol and the required resume behavior;
- stop conditions for an unexpected prompt, state mismatch, or denied request.
For example:
Prepare release 1.2.3 from the repository root.
Start by running:
./scripts/release continue 1.2.3
The Blessed Script owns all gh and aws operations. Do not run those Tools
directly. If the script exits 75, follow the prompt it prints, write only the
requested output file, then run the exact resume command from that prompt.
Stop and report the output if the script reports a state mismatch, requests a
different version, or names an entry point not listed in its first prompt.
Avoid broad requests such as “finish the release.” A broad request invites the agent to search for another route when the script pauses or denies an operation. The initial prompt should make the script the only authority-bearing interface for the workflow.
Craft each handoff prompt
A handoff prompt should stand on its own. Agent context can be compacted or lost during a long task. Include the operation identifier and repeat the boundary that matters for the next step.
Name these details:
- the exact artifact to produce, including its path and format;
- the decision criteria and size or schema limits;
- fixed context entry points the agent may invoke;
- the exact command that resumes deterministic work;
- commands and data the agent must not access;
- conditions that require the agent to stop instead of guessing.
Keep volatile context out of the prose when the agent can fetch a fresh view through a fixed entry point. A prompt that embeds yesterday's deployment state can send the next invocation down the wrong branch.
Choose capabilities before writing prompts
A Script Declaration lists the Authorization Gates the script may use and the maximum Capability at each gate. Declare the weakest capability that covers every branch. A capability is a ceiling; the gate still classifies and authorizes each concrete operation.
# --- automic-vault
# capabilities:
# gh: write
# aws: read-only
# ---
Review capabilities across all entry points. Recovery, cleanup, status, and retry branches can request more authority than the main operation. Remove a branch that needs unrelated authority or place it in another Blessed Script.
One write-capable branch raises the declaration ceiling for that gate across the whole script. Split context gathering from publication when a reviewer should be able to bless or endorse them independently. A separate read-only script can serve context while the publishing script retains Approval Required or a narrow Launcher Endorsement.
Capabilities govern Automic Vault Authorization Gates. Ordinary file reads, interpreter behavior, and ungated network clients remain outside that boundary. Keep the script short enough to review and avoid calling alternate Tools that bypass the declared gates.
Keep Secret Values away from the agent step
Prefer a Tool-specific Gate over direct environment injection.
Tool-specific Gates can classify the operation and apply only the
credential that Tool needs. Direct av inject +NAME places
the raw Secret Value in the interpreter's environment, where script
branches and child processes can read it.
End the secret-bearing process before asking the agent for input. The agent then works between invocations and receives only the prompt, bounded context, and non-secret state. The next invocation obtains its own Authorization Decision before Secret Application.
Do not write Secret Values, bearer tokens, proxy credentials,
authorization headers, or complete command environments into prompts or
run-state files. Avoid set -x, env, verbose
HTTP traces, and unfiltered Tool responses in agent-facing entry points.
Select the fields the agent needs and redact output at its source.
Secret Application gives the Target control of the Value after release. A Blessing cannot stop an authorized Tool or dependency from logging or returning it. Choose a narrower Target and operation when the Tool exposes a safer route.
Inventory what the agent may need later
Walk through the workflow from each pause to the next side effect. For every agent decision, list the evidence required to make it and decide who supplies that evidence:
| Need | Safer interface | Avoid |
|---|---|---|
| Recent changes | Fixed subcommand returning bounded commit fields | General shell access for repository discovery |
| Remote release state | Fixed Tool query with selected JSON fields | Arbitrary gh or API commands |
| Artifact identity | Script-produced path, size, and digest | Asking the agent to locate “the latest” file |
| Prior failure | Sanitized log or agent:last-failure entry point |
Debug traces containing environments or headers |
| Resume state | Per-run state plus a fresh remote check | State held only in conversation history |
Long workflows often pause on branches that the happy path never visits. Plan for a remote object that exists, a CI job that has not finished, an expired session, a partially uploaded artifact, and a changed local checkout. Give the agent a fixed inspection command for any case where judgment can help. Make the script fail with a precise diagnostic when only the operator can resolve the state.
Context entry points should return the minimum fields required for a decision. Use fixed repository, account, region, bucket, and query values in the script. Validate any selector the agent supplies. Do not accept a free-form Tool command or query language as an argument because that turns a reviewed entry point into a general capability proxy.
Treat issue bodies, release notes, logs, and remote metadata as untrusted input. They may contain instructions aimed at the agent. Label them as reference data in the prompt, trim fields that carry no decision value, and keep their contents out of shell evaluation.
Persist non-secret workflow state
Use a run directory keyed by a validated operation identifier. It may contain:
- immutable inputs such as repository and version;
- artifact paths, sizes, and cryptographic digests;
- the current handoff prompt and expected output path;
- verified remote identifiers and completed-step markers;
- sanitized failure details needed for the next decision.
Create the directory with owner-only permissions. Reject symlinks and files owned by another user. Bound file sizes and write state through a temporary file followed by an atomic rename. State files are inputs at the next trust boundary; validate them again when reentering.
Keep Secret Values out of state. Fetch volatile authorization and remote status again on each invocation. A stored “uploaded” marker does not prove that the remote object still matches, so compare its digest or immutable identifier before advancing.
Validate agent output as untrusted input
Ask the agent to write a fixed file rather than place substantial content in a command argument. The script controls the path and can enforce file properties before it reads the content.
Check the expected type, owner, symlink status, byte limit, encoding, and schema. Apply destination-specific rules, such as an allowed deployment target or release-note heading. Reject unknown fields when structured output drives a privileged action.
Pass validated content as data. Use options such as
--notes-file instead of shell interpolation. Never
eval, source, or execute agent output. Do not
let an output file choose the next entry point, Tool command, Secret
Name, account, or destination unless the script validates it against a
reviewed allowlist.
Recheck local artifacts and remote state after validation. Both can change while the agent works. Refuse the operation when the fresh state conflicts with the state the agent used.
Make resume and retry safe
The continue entry point should tolerate interruption
after any remote side effect. Before creating an object, query the
destination:
- continue when the object is absent;
- verify and skip when it exists with the expected identity and digest;
- stop when it exists with different contents or ownership.
Use service idempotency keys, conditional writes, and immutable object names where available. Record a completed step only after checking the remote result. A retry must not replace a conflicting object to make progress.
Regenerate time-sensitive prompts and context on reentry. Credentials, Approval eligibility, CI state, signed URLs, and locks can expire while the agent works. The new invocation should discover that state and either proceed, print another bounded prompt, or fail closed.
Example reentry sequence
- The agent runs
./release continue 1.2.3from the initial prompt. - The script finds no notes, prints the handoff prompt, saves it, and exits 75.
- The agent invokes the listed context entry points and writes the fixed notes file.
- The agent runs the exact
continuecommand from the handoff prompt. - Automic Vault makes a new Authorization Decision. The script validates the notes and fresh remote state, then performs the next deterministic step.
- If the process stops after a side effect, the next
continueverifies that result and resumes without duplicating or overwriting it.
The full defensive release script shows input validation, bounded context commands, digest checks, conditional S3 writes, and idempotent retries.
Review checklist
- Every action and argument has a fixed, validated shape.
- The initial prompt names the first command and the reentry protocol.
- Each handoff prompt names one output, bounded context, and one resume command.
- The Script Declaration uses the weakest gate capabilities that cover all branches.
- Agent-facing output contains no Secret Values or general Tool access.
- Run-state files contain no credentials and receive trust-boundary validation.
- Agent output stays data and cannot select arbitrary commands or destinations.
- Each side effect has a remote verification and conflict path.
- Repeating
continueis safe after interruption. - Unexpected state stops the workflow with a precise diagnostic.