Services
A Triggers service is the runtime boundary that owns action handlers, ingress declarations, and capability metadata. When a service starts, it registers a manifest over NATS so the orchestrator knows what that service can do.
What the runtime learns from a service
The service manifest is more than a name and version. It tells the runtime:
- which actions exist
- which
service_sourcesexist and what transport each one uses - which node kinds the service supports, such as
conditionormapping - the manifest hash that identifies the currently advertised capability set
- optional transport metadata that Studio can use when constructing flow targets
That is why registration is the first thing to verify when a flow is not behaving. If the runtime has the wrong manifest, the graph can be valid in Studio and still fail in practice.
Actions
Actions are the executable units inside a service. Each action carries:
- input schema
- result schema
- timeout
- retry policy
- DLQ target
- optional
result_eventcatalog metadata for downstream binding; the current Go and Python SDKs auto-derive it for flat typed object outputs with derivable fields, while empty outputs omit it unless you override it
In practice, the runtime invokes the action when a released flow reaches that service segment. The action's result payload continues through the graph, while CompletionEvent is emitted separately for observability.
service_sources are ingress capability, not top-level flow sources
This distinction is easy to miss:
- a top-level source starts a flow run
- a
service_sourcedescribes what a service segment can receive
For example, flow_lab_in is a flow-starting source. nats on flow_lab is a service ingress declaration. They are related during end-to-end execution, but they are not the same thing and they are registered differently.
Manifest hash and drift
The manifest includes a manifest_hash so the system can identify the concrete capability set currently advertised by a service. When you are debugging rollout drift, compare:
- the released flow version
- the live
manifest_hash - the service's visible actions and
service_sources
If those do not line up, the runtime may be executing against capability that differs from what you think is deployed.
Liveness matters separately from manifest storage
The fleet APIs can show a service manifest even when the service is currently offline. Treat these as separate questions:
- does the runtime know about this service's manifest?
- is the service online right now and sending heartbeats?
For local debugging, GET /api/v2/services/<service> is the fastest answer because it gives you both liveness and manifest detail in one place.
Example service shapes in this repo
Two concrete examples are useful:
flow_labis the minimal local dummy: one NATS service ingress, two actions, and chained output metadata for downstream binding.notify-senderis a more production-shaped Go service: multiple actions, three service sources (nats,kafka,http),conditionandmappingcapability, and Redis-backed dedup.
The difference is helpful. flow_lab teaches the loop. notify-sender shows what a richer service registration looks like without changing the core runtime model.
Practical inspection points
Use these first:
GET /api/v2/services/<service>for one service's liveness and manifestGET /api/v2/servicesfor fleet-wide inventoryGET /api/v2/fleet/releaseswhen you need to line up service state with released flow state
Read next
- /triggers/python-sdk for the Python service-authoring model
- /triggers/go-sdk for the Go service-authoring model used by
flow_labandnotify-sender - /triggers/sources for ingress and source registration details