Best Practices¶
Recommended conventions for writing HERY entities and building Amadla-compatible tools. These are not enforced by the system — they are good hygiene that makes entities more discoverable, composable, and maintainable.
entity_types Convention¶
When an entity needs to communicate which entity types it supports, targets, or operates on, use the field name entity_types in _body.
This is not a reserved property — it lives inside _body and is schema-defined. But using a consistent name across the ecosystem makes entities easier to understand and query.
Where It's Used¶
| Entity | Field | Purpose |
|---|---|---|
| Template | entity_types |
Which entity types this template can render for |
Example¶
_type: amadla.org/entity/template@v1.0.0
_body:
engine: jinja2
source: ./templates/nginx.conf.j2
output: /etc/nginx/conf.d/myapp.conf
entity_types:
- amadla.org/entity/application@^v1.0.0
- amadla.org/entity/application/webserver@^v1.0.0
Why Not a Reserved Property?¶
Reserved properties (_type, _extends, _meta, _body, _requires) are fixed — they have universal meaning across all entities. entity_types is domain-specific: its meaning depends on context (a template "renders for" certain types). Keeping it in _body means each schema defines its own semantics.
Tools Entity: Keep It Minimal¶
The Tools entity only has two properties per tool: name and optional path. Everything else (what entity types a tool handles, its version, capabilities) comes from calling <tool> info at runtime.
_type: amadla.org/entity/tools@v1.0.0
_body:
tools:
- name: hery
- name: lay
- name: enjoin
- name: weaver
- name: raise
- name: doorman
path: /opt/secrets/bin/doorman
Don't put routing, descriptions, or caching config in the tools entity. The tools self-describe via their info subcommand — the entity is just a registry of names and locations.
Tool Input: File Path or Stdin¶
All Amadla tools must accept entity data via file path or stdin:
# File path
weaver render -f ./entities/template.hery
# Stdin (UNIX piping)
cat ./entities/template.hery | weaver render
# Pipeline
hery query --type '*/template@*' -o json | weaver render
This is core UNIX philosophy. Tools that only accept one input method break composability.
Keep Entities Focused¶
Each entity should describe one concern. Don't mix template configuration with package installation with security policies. Separate concerns into separate entities and use _requires to declare dependencies between them:
# package.hery — what to install
_type: amadla.org/entity/package@v1.0.0
_body:
packages:
- nginx
# template.hery — what to render
_type: amadla.org/entity/template@v1.0.0
_requires:
- amadla.org/entity/package@v1.0.0
_body:
engine: go
source: nginx.conf.tmpl
output: /etc/nginx/nginx.conf
Exit Codes¶
Tools should exit with standard UNIX codes:
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Failure (tool-specific error) |
2 |
Usage error (bad arguments, missing required flags) |
The orchestrator (amadla) reads exit codes to determine pipeline flow. Don't use custom exit codes beyond these three.
Data Flow: stdout for Data, stderr for Diagnostics¶
- stdout — structured output (JSON, YAML, rendered content)
- stderr — logs, warnings, progress messages, errors
This allows tools to be piped without diagnostic messages corrupting the data stream.