Step 1: Hello World
Let's start with the simplest possible pipeline—one that just prints "Hello, World!" every second.
Create the Pipeline
Create a file called hello.yaml:
input:
generate:
interval: 1s
mapping: |
root.message = "Hello, World!"
pipeline:
processors:
- log:
message: '${! content() }'
output:
stdout: {}
Check it before you run anything. This is offline and needs no node, no account and no network:
expanso-edge validate hello.yaml
Run It
hello.yaml is a pipeline config. Expanso executes pipelines as jobs, so
wrap it in a job spec that gives it a name and a type:
name: hello-world
type: pipeline
config:
input:
generate:
interval: 1s
mapping: |
root.message = "Hello, World!"
pipeline:
processors:
- log:
message: '${! content() }'
output:
stdout: {}
Then deploy it to Expanso Cloud, which schedules it onto a connected edge node and keeps it managed by the control plane. This series is written against that route.
Prerequisites: an Expanso Cloud workspace, a saved CLI profile with an API key, and at least one connected edge node. One-time setup is in Deploy to Cloud.
expanso-cli job deploy hello-job.yaml
expanso-cli job logs hello-world
Expanso Edge also runs standalone: expanso-edge run --local starts an agent
with no control-plane connection and its own API on port 9010, which you can
deploy the same job spec to. That mode is documented separately in
Local Mode — the later steps here assume the Cloud
route, so follow Local Mode's own pages rather than mixing the two.
Verify It Worked
job logs streams the pipeline's log. Every second the log processor adds a
line that ends with the message. Each line starts with the node, a timestamp
and labels (shortened to {…} here):
[my-node] 2026-10-02T18:11:08.721Z {…} {"message":"Hello, World!"}
[my-node] 2026-10-02T18:11:09.721Z {…} {"message":"Hello, World!"}
Lines about writing to stdout appear in between. The stdout output itself
prints to the agent's terminal on the node, not to job logs.
If nothing appears, the job was accepted but is not executing. job deploy
returns after the control plane stores the job, not after a node picks it up, so
check the assignment:
expanso-cli job describe hello-world
expanso-cli node list
An empty node list means no node is connected to run it. More failure modes are in Testing & Debugging.
Stop the job when you are done:
expanso-cli job stop hello-world
--config does not run a pipelineexpanso-edge run --config loads agent settings, not pipeline YAML. Passing a
pipeline config to it reports the input, pipeline and output keys as unknown
fields and ignores them: the agent starts and your pipeline never runs.
What Just Happened?
| Component | What It Does |
|---|---|
input.generate | Creates data from nothing (no external source needed) |
interval: 1s | Generates a new message every 1 second |
mapping | Uses Bloblang to define the message structure |
log processor | Writes each message to the pipeline's log, which job logs streams |
output.stdout | Prints each message to the agent's terminal on the node |