Output Engine
Outputs are generated in the fourth pipeline phase, after assets, models, and compliance have been applied. Each output file (output/*.toml or output/*.jsonnet) loops over an origin_resource type and renders one artifact resource per matching node.
Artifact bodies can be rendered with text-based Tera templates or native Jsonnet expressions (jsonnet = '''...'''). Jsonnet is particularly powerful for complex, nested data structures (such as Kubernetes manifests or Terraform configurations) because it constructs JSON directly with variables, conditionals, list comprehensions, and sibling .libsonnet imports rather than text interpolation.
An output rule produces a new graph resource (linked to the origin via DESCRIBED_BY) and stores the rendered content. Resource names and filenames can be templated with the full traversable origin_resource context.
Strict Validation: All
[[output]]blocks enforce strict key validation. Misspelled, unsupported, or misplaced keys (such astarget_idorcreate_relation) produce a parse error rather than failing silently. Supported keys are:resource_type,name,filename,mimetype,relation,match_on,depends_on,template, andjsonnet.
Filenames may be simple names (e.g. report.txt) or relative paths (e.g. .agents/skills/{{ origin_resource.name }}/SKILL.md). Absolute paths and paths containing .. are rejected when artifacts are exported to disk.
Dependency ordering with depends_on
An output rule can declare that its artifact depends on another output artifact. After all output rules stabilize, rescile resolves each declaration into a DEPENDS_ON edge from the dependent output to the dependency output. Tools that export artifacts (such as rescile-ce save --outputs or rescile-ee serve --write-outputs) use these edges to write dependencies before dependents, and to detect dependency cycles.
[[output]]
resource_type = "agent_skill"
name = "skill-{{ origin_resource.name }}"
filename = ".agents/skills/{{ origin_resource.name }}/SKILL.md"
depends_on = [
{ resource_type = "developer_source_artifact", name = "as-{{ origin_resource.name }}" }
]
template = "..."
Both resource_type and name are rendered with the same Tera context as the output itself, so they can reference origin_resource and relation. If the named dependency does not exist, a warning is emitted and the edge is skipped.
Relation-bound outputs
An output file (or a single output rule) can be bound to a relation. When relation is set at file level, it applies to every [[output]] rule in the file unless a rule sets its own relation. The rule expands once per outgoing edge with that relation label from the origin node, and the current edge is exposed as a top-level relation variable.
origin_resource = "compute"
relation = "DEPLOYED_AS"
[[output]]
resource_type = "deployment_target"
name = "target-{{ origin_resource.name }}-{{ relation.target.properties.name }}"
filename = "{{ origin_resource.name }}-{{ relation.target.properties.name }}.json"
template = '''
{
"instance_type": "{{ relation.properties.instance_type }}",
"encrypted": {{ relation.properties.encrypted | default(value=false) }},
"provider": "{{ relation.target.properties.name }}"
}
'''
Available fields:
relation.label— the relation label, e.g.DEPLOYED_AS.relation.properties.<name>— any property stored on the edge.relation.target.labelandrelation.target.properties.<name>— the node on the other end of the relation.
When relation is omitted, the rule renders a single artifact per matching origin node.
Scoping precedence
A file-level relation applies to every [[output]] rule in the file. If a rule sets its own relation, the rule-level value wins. If neither is set, the rule renders one artifact per matching origin node as usual.
origin_resource = "compute"
relation = "DEPLOYED_AS" # default for every rule below
[[output]]
resource_type = "node_manifest" # uses DEPLOYED_AS
name = "node-{{ origin_resource.name }}"
...
[[output]]
relation = "BACKED_UP_TO" # overrides the file-level default
resource_type = "backup_manifest"
...