Skip to content

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

runtime capability validate my-cap
runtime capability execute  my-cap --input path=./notes.txt

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

runtime capability execute files/notes-roundtrip \
  --input path=./notes.txt \
  --input message=hello

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.