Skip to main content

Interpreters (user view)

For a user, a Courier interpreter represents a capability, not a tool. It’s the unit of execution a user selects when they want a specific kind of work to be performed as part of a larger operational process.

Users don’t interact with interpreters as binaries, scripts, or plugins. They interact with them as named, documented behaviors that can be safely composed into Courier jobs.

The interpreter as intent

A Courier interpreter exists to express and enforce intent.

When a user selects an interpreter for a job step, they’re not choosing how work should be performed. They’re declaring what outcome they want to achieve within the bounds of that interpreter’s contract.

Each interpreter constrains one or more underlying actions into a single, well-defined intent. This constraint is deliberate. It allows complex or multi-step operations to be represented as a single step that’s easy to reason about, reuse, and audit.

In Courier, there is a one-to-one relationship between a job step and an interpreter invocation. One step represents one intent. If a workflow requires multiple intents, it’s expressed as multiple steps rather than by overloading a single interpreter invocation.

Because of this model, interpreters are chosen, not scripted. Users select interpreters based on the capability they provide and the guarantees they offer, rather than writing imperative instructions or assembling command sequences.

What users expect from an interpreter

When users rely on an interpreter as part of a Courier job, they implicitly depend on a set of expectations. These expectations aren’t optional; they’re what make interpreters usable as building blocks for operational workflows.

Users expect:

  • Consistency
    Given the same inputs and conditions, an interpreter behaves in the same way across runs and environments (when technically feasible).

  • Predictability
    The interpreter’s behavior, side effects, and outputs align with its documented contract and don’t change unexpectedly.

  • Safety
    The interpreter constrains what can be done, validates inputs, and prevents unsafe or unintended actions.

  • Clear outcomes
    The interpreter produces structured results that clearly indicate what happened, what succeeded or failed, and what can be acted on next.

  • Stable behavior over time
    Once a user builds automation around an interpreter, they can rely on its contract to remain stable, evolving only in well-documented and non-breaking ways.

These expectations allow users to compose interpreters into higher-level processes with confidence, without needing to understand or control the underlying execution engines.

What an interpreter isn’t

Understanding what an interpreter is also requires understanding what it’s not. Interpreters intentionally avoid several patterns that would undermine their role as stable, intent-driven capabilities.

An interpreter isn’t a general-purpose script runner. It doesn’t accept arbitrary code or free-form commands and it doesn’t expose unrestricted execution.

In rare and explicitly documented cases, specific interpreters (shell, bash, remote-shell, and powershell) may be provided as intentional escape hatches that allow general-purpose execution. These interpreters exist to support exceptional scenarios where constraint isn’t practical or where legacy workflows must be accommodated. Such interpreters must clearly signal their elevated risk, reduced guarantees, and broader execution scope, and should be treated as opt-in exceptions rather than the default model.

An interpreter isn’t an orchestration engine. It doesn’t manage control flow, retries, branching, or coordination across steps. Those concerns are handled by the Courier job and the Courier Runner.

An interpreter isn’t a CLI passthrough. It doesn’t simply mirror the flags or options of an underlying tool. Exposing raw engine interfaces defeats the purpose of having an interpreter contract.

An interpreter isn’t a workflow manager. It performs one step, expresses one intent, returns its results, and exits.

These constraints are intentional. By limiting what an interpreter can do, Courier ensures that interpreters remain predictable, composable, and safe to use as long-lived building blocks in operational processes.

Thank you for your feedback!

×