Skip to main content

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_sources exist and what transport each one uses
  • which node kinds the service supports, such as condition or mapping
  • 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_event catalog 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_source describes 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_lab is the minimal local dummy: one NATS service ingress, two actions, and chained output metadata for downstream binding.
  • notify-sender is a more production-shaped Go service: multiple actions, three service sources (nats, kafka, http), condition and mapping capability, 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 manifest
  • GET /api/v2/services for fleet-wide inventory
  • GET /api/v2/fleet/releases when you need to line up service state with released flow state