MODELS, TYPES, AND METHODS
Why types and definitions are separate
Swamp separates model types from model definitions because they change for different reasons, are authored by different people, and live in different places.
A model type is TypeScript code. It defines methods, input and output schemas, and execution logic for interacting with an external system. A model definition is YAML configuration. It instantiates a type with specific arguments — which region, which CIDR block, which command to run. The analogy is straightforward: a type is a class; a definition is an object constructed from it.
The separation exists to make two things possible. First, types are published as
extensions and shared across repositories.
A collective publishes an EC2 model type once; any repo can write a definition
that uses it. Second, definitions are plain structured data, not code. An agent
can produce a YAML definition using general reasoning — it writes data
conforming to a schema, and the type handles execution. This means an agent does
not need to understand the TypeScript internals of a model type to use it. It
only needs to understand the schema, which is inspectable via
swamp model type describe.
The tradeoff is indirection. When something goes wrong, you need to know whether the problem is in the type (code) or the definition (configuration). Swamp surfaces this through schema validation at definition creation time — if the YAML does not match the type's input schema, the error points at the definition. If the schema validates but execution fails, the problem is in the type.
See the model definitions reference for the YAML schema and the model type reference for the TypeScript interface.
The method execution model
Methods are named operations on a model — create, start, stop, destroy,
sync, lookup, and whatever else a type defines. The execution lifecycle has
a deliberate shape: definition evaluation, pre-flight checks, method execution,
data output write.
The ordering matters most at the pre-flight stage. Checks run before the method executes because they enforce invariants — policy constraints, dependency readiness, quota availability — that are cheaper to verify than to recover from. A half-completed cloud provisioning operation that fails mid-execution may leave orphaned resources. A check that fails before execution begins leaves nothing to clean up.
Definition evaluation resolves CEL expressions in the YAML at execution time,
not at creation time. This means a definition can reference the output of
another model (data.latest("vpc", "resource").attributes.id) and the value is
resolved when the method runs, not when the definition is written. Late binding
is what makes data chaining across models work — see
How Swamp Works for the broader
composition model.
After execution, the method's output is written as versioned, immutable data.
This is not optional — every method execution produces data artifacts, even if
the method's purpose was destructive. A destroy method writes a record that
the destruction happened, what was destroyed, and when. This is what makes the
data layer useful for audit and for downstream decisions.
Auto-creation vs explicit definitions
Swamp supports two paths to running a model method. The explicit path is
swamp model create, which produces a definition file tracked in the
repository. The implicit path is direct type execution
(swamp model method run @type method_name), which auto-creates a definition in
.swamp/auto-definitions/ if one does not already exist.
Auto-creation exists for two reasons: rapid prototyping and agent ergonomics. An operative exploring a new model type should not have to write a definition file before they can try a method. An agent executing a one-off task should not produce permanent configuration for something that will not be repeated.
The tradeoff is visibility. Auto-definitions are ephemeral — they are not
git-tracked, do not appear in swamp model search, and are not included in
workflow resolution. If a model needs to be referenced by other models, composed
into a workflow, or reviewed by a teammate, it needs an explicit definition.
Auto-creation is the sketch; explicit definition is the committed design.
Output specs: resources vs files
Method outputs come in two forms, and the distinction is intentional.
Resources are structured JSON conforming to a schema. They are queryable via
data.latest() and composable — one model's resource output becomes another
model's input through CEL expressions. Resources are the composition mechanism
that makes model chaining work.
Files are opaque binary or text artifacts with MIME types — logs, generated configuration, downloaded content. They are stored and retrievable, but they are not queryable by field or composable through expressions. A file is an artifact you keep; a resource is data you build on.
The reason for the split is that treating everything as structured data would force schemas onto content that has no meaningful structure (a log file, a tarball), while treating everything as opaque files would destroy the composability that makes models useful together.
The built-in command/shell type
Every Swamp installation ships with command/shell, a model type that runs
arbitrary shell commands. It exists as an escape hatch — a way to do something
Swamp does not have a typed model for, without leaving Swamp's data model
entirely. The command runs, and its stdout, stderr, and exit code are captured
as a structured resource, queryable like any other output.
The escape hatch is deliberately uncomfortable for repeated use. Shell commands
have no input schema, no output schema beyond the generic result shape, and no
pre-flight checks. If you find yourself wrapping a CLI tool in command/shell
across multiple definitions, that is a signal to search for a community
extension (swamp extension search) or write an
extension model that gives the interaction
proper types. The repository convention makes this explicit: command/shell is
for ad-hoc one-off commands, not for building integrations.
Related
- How Swamp Works — the broader composition model that types, definitions, and methods fit into.
- Model Definitions — YAML schema for model definitions.
- Model Type Interface — TypeScript interface for extension model types.