Interpreters (system view)
From a system perspective, a Courier interpreter exists to perform a narrowly defined role within the execution of a job. That role is intentionally constrained. By limiting the responsibilities of an interpreter, Courier ensures that interpreters remain predictable, composable, and safe to use as long-lived building blocks.
This section describes the responsibilities an interpreter must fulfill, the responsibilities it must not assume, and why interpreters function as critical security boundaries within the Courier model.
Interpreter responsibilities
An interpreter is responsible for executing exactly one job step by performing the following functions:
Receive structured intent
The interpreter receives a single invocation containing structured input that expresses user intent according to the interpreter’s contract. The interpreter doesn’t infer intent from context or external state.Validate interpreter-specific commands
The interpreter validates that the received intent conforms to its contract. This includes verifying required fields, enforcing constraints, and rejecting invalid or ambiguous input. Validation failures must be explicit and human-readable.Translate intent into execution
The interpreter translates validated intent into one or more concrete operations against its underlying execution engine. This translation may involve multiple commands, API calls, or runtime actions, but these details remain internal to the interpreter.Return structured results
Upon completion, the interpreter returns a structured result that clearly communicates outcomes, relevant data, and any artifacts produced. This structured result represents the interpreter’s contractual output and is intended for downstream consumption by jobs and automation.Interpreters may also emit diagnostic information to standard output and standard error for logging and troubleshooting purposes. Such output is considered non-contractual and must not be required for interpreting results or driving job behavior.
In some cases, users may choose to apply Courier output rules to transform or extract value from unstructured output produced by an interpreter. While this capability enables flexibility and integration with legacy tools, it’s explicitly a downstream concern. Interpreters shouldn’t rely on output rules to compensate for missing or incomplete structured results, and should always aim to return well-defined, structured data directly into the job context.
Terminate
After producing its results, the interpreter exits. It doesn’t retain state, spawn background processes, or continue execution beyond the scope of the job step.
These responsibilities are intentionally minimal. An interpreter that performs only these functions is easier to reason about, test, secure, and evolve.
Responsibilities explicitly outside the interpreter
To preserve clarity of behavior and separation of concerns, several responsibilities are explicitly outside the scope of an interpreter and must be handled elsewhere in the Courier system.
An interpreter must not perform:
Orchestration
Interpreters don’t determine step ordering, parallelism, or job structure.Retries
Interpreters don’t decide if or when a step should be retried. They report outcomes; retry logic is handled by the Courier job and Runner.Conditional logic
Interpreters don’t branch execution based on prior steps or external conditions.Cross-step coordination
Interpreters don’t communicate directly with other interpreters or share state beyond structured output (and job context).Output extraction
Interpreters don’t control how their output is stored, propagated, or mapped into the job context. They return results; the Runner handles extraction.
Keeping these concerns out of interpreters prevents hidden coupling, inconsistent behavior, and fragile workflows.
Interpreters as security boundaries
Interpreters aren’t merely execution components; they’re security boundaries.
By constraining how intent is expressed and how execution occurs, interpreters reduce the risk inherent in automation. Constraint is a feature, not a limitation. It limits blast radius, prevents accidental misuse, and makes behavior auditable.
Interpreters reduce risk by:
- Restricting what actions can be performed
- Validating and sanitizing inputs before execution
- Preventing exposure of raw engine interfaces
- Encapsulating sensitive operations behind documented contracts
The interpreter contract is the primary enforcement point for these constraints. It defines what’s allowed, what’s rejected, and what guarantees are provided. Users rely on these contracts to understand the safety and impact of their jobs. Implementers rely on them to enforce consistent behavior.
By treating interpreters as enforcement points rather than mere adapters, Courier ensures that operational power is delivered with appropriate guardrails.