Validate & Execute¶
The working loop for capabilities. Command-level detail is in
runtime capability; this page is the practice.
Building your first one? Create a Capability walks the full sequence; this page goes deeper on the validate/execute half of it.
Always validate first¶
Validation resolves every step against the operation surface of the binary
you are running, so a typo, a renamed operation or a binary missing from
allowed_binaries fails before anything executes.
It reports every problem it finds, not just the first — so one run tells you everything to fix.
What validation checks¶
| Check | Failure looks like |
|---|---|
version present |
missing version |
| At least one step | no workflow steps |
Exactly one of provider / binary per step |
a step setting both, or neither |
| Provider is registered | a step naming an unregistered provider |
args resolve to a real operation |
a step whose args don't match any operation of that provider |
binary is in allowed_binaries |
a step naming a binary policy doesn't permit |
| Only known keys | an unrecognized key, named with its line number |
${...} placeholders are probe-substituted before operation matching, so
unresolved inputs don't produce confusing false failures.
What validation does not promise¶
A capability that validates is well-formed and only references things this runtime version can run. It can still fail at execution:
- missing or expired credentials
- a step denied by policy
- a network error
- an operation that is valid but wrong for the target (a repo that doesn't exist)
Validation is a structural guarantee, not a success guarantee.
Executing¶
Execution re-validates, checks required inputs, substitutes ${name}, then
runs each step in order.
Machine-readable output¶
runtime --output json capability execute files/notes-roundtrip \
--input path=./notes.txt --input message=hello
Returns a result covering every step. --output is a global flag, so it
goes before capability.
Execution semantics¶
Stops at the first failing step. Steps before it have already run and are already audited.
step 1 ✓ executed, audited
step 2 ✓ executed, audited
step 3 ✗ failed → execution ends here
step 4 never runs
Capabilities are not transactional
There is no rollback. If a workflow creates a repository in step 2 and fails in step 7, the repository still exists.
Design for this: put the destructive or expensive steps late, make workflows re-runnable where you can, and where you can't, say so in the prose. Several shipped examples are deliberately not idempotent — they create a fresh target per run instead.
Each step's own audit record is written, including the transport its provider chose. The capability itself contributes no execution logic and no separate record.
The authoring loop¶
# 1. discover what exists
runtime github --help
cat ~/.engineering-runtime/commands/github_commands.txt
# 2. check a single command line, with zero side effects
runtime resolve github repo summary cli/cli
# 3. run it for real, once, to see the shape of the output
runtime github repo summary cli/cli
# 4. write the capability, then validate
runtime capability validate ./my-cap.md
# 5. execute
runtime capability execute ./my-cap.md --input repository=cli/cli
# 6. confirm what actually happened
runtime audit tail -n 10 --output json
Steps 2 and 3 are where most authoring time is saved: proving a single operation works before embedding it in a nine-step workflow.
Validating a whole directory¶
Worth doing after every runtime upgrade — an operation may have changed:
export RUNTIME_CAPABILITIES_DIR=~/work/team-capabilities
find "$RUNTIME_CAPABILITIES_DIR" -name '*.md' -print0 |
while IFS= read -r -d '' f; do
runtime capability validate "$f" >/dev/null || echo "FAILED: $f"
done
In CI, drop the >/dev/null and let a non-zero exit fail the job. See
CI/CD.
Diagnosing a failure¶
| Symptom | First check |
|---|---|
unregistered provider |
runtime config validate — is the provider in the Runtime Providers section? |
| Args don't resolve to an operation | runtime <provider> --help — the operation may not exist in your version |
binary not allowed |
runtime config validate — your policy-config.yaml may predate the release that added it |
| Step denied at execution but validated fine | Policy denies the specific arguments, not the operation. Check Policy |
Literal ${name} in the output |
An input was declared but not supplied |
| Works by path, fails by name | The capabilities directory isn't where you think — check runtime config validate |
More: Troubleshooting.