Pipeline YAML Reference¶
This page documents every field in the pipeline YAML format. For the concepts behind these fields (state, execution order, templating), see Concepts.
A full example:
graph_version: V1
name: My Agent
provider_configs:
my-openai-config:
id: my-openai-config
provider: OpenAI
api_key: null # falls back to OPENAI_API_KEY env var
base_url: null # null = default OpenAI endpoint
nodes:
- !Start
id: start-node
label: lathe::nodes::start
- !LLMNode
id: llm-node
label: My LLM Step
provider: OpenAI
model: gpt-4o-mini
system_prompt: You are a helpful assistant. The user's name is {{/user_name}}.
input_key: /message
output_key: /response
provider_config_id: my-openai-config
tools:
- my-http-tool
- !End
id: end-node
label: lathe::nodes::end
out_pointers:
- /response
connections:
- from: start-node
to: llm-node
label: lathe::nodes::start to My LLM Step
- from: llm-node
to: end-node
label: My LLM Step to lathe::nodes::end
tools:
my-http-tool:
kind: HttpRequest
name: my-http-tool
description: Looks something up over HTTP.
method: GET
url: https://example.com/api?q={{query}}
headers:
Authorization: Bearer ${MY_API_KEY}
body: null
timeout: 5000
response_type: Json
params:
query:
type: Text
description: The search query.
Top-level fields¶
| Field | Type | Description |
|---|---|---|
graph_version |
string | Schema version. Only V1 is currently supported. |
name |
string | A human-readable name for the pipeline. |
nodes |
list | The graph's nodes. See Nodes. |
connections |
list | The graph's directed edges. See Connections. |
provider_configs |
map | LLM provider credentials and endpoints, keyed by id. See Provider Configs. |
tools |
map | (optional) Tools that LLMNodes may call, keyed by id. See Tools. |
YAML tag syntax¶
Each entry in nodes is tagged with !Start, !LLMNode, or !End — this tag selects which node type the following fields belong to. It's YAML's syntax for a tagged union: the tag isn't a comment or a custom type name you choose, it's one of the three fixed node kinds Lathe understands. Every node in the list needs exactly one of these tags.
Nodes¶
Start¶
| Field | Type | Description |
|---|---|---|
id |
string | Unique node identifier, referenced by connections. |
label |
string | Human-readable label. |
Constraints:
- Exactly one
Startnode is required per graph — it's the entry point. See Validation rules. - It passes the initial
AgentStatethrough unchanged. If the initial state is empty, it errors.
LLMNode¶
| Field | Type | Description |
|---|---|---|
id |
string | Unique node identifier, referenced by connections. |
label |
string | Human-readable label. |
provider |
OpenAI | LMStudio |
Which LLM provider to call. |
model |
string | Model name to request from the provider. |
system_prompt |
string | System prompt sent to the model. Supports {{/pointer}} templating — see Concepts § Template resolution. |
input_key |
JSON Pointer | Where to read the user message from in AgentState. |
output_key |
JSON Pointer | Where to write the LLM's response in AgentState. |
provider_config_id |
string | Id of an entry in the top-level provider_configs map to use for this node. |
tools |
list of strings | (optional) Ids from the top-level tools map that this node's LLM may call. Defaults to an empty list. See Tools. |
Unknown tool id panics
Every string in tools must match a key in the top-level tools map. An id that doesn't resolve panics when the graph is materialized, rather than failing gracefully.
Unmatched provider_config_id falls back silently
If provider_config_id doesn't match any key in provider_configs, the node does not error — it silently falls back to an auto-generated default config for the node's provider (default endpoint, no API key set explicitly, so it still relies on OPENAI_API_KEY for OpenAI). If a node seems to be hitting the wrong endpoint or credentials, double-check this id matches a real key in provider_configs.
End¶
| Field | Type | Description |
|---|---|---|
id |
string | Unique node identifier, referenced by connections. |
label |
string | Human-readable label. |
out_pointers |
list of JSON Pointers | Which keys from the final AgentState to surface as the pipeline's output. |
Constraints:
- Every leaf node (a node with no outgoing connections) must be an
Endnode, and everyEndnode must be a leaf node. A graph that violates this fails validation.
Connections¶
Each entry is a directed edge from one node to another:
connections:
- from: start-node
to: llm-node
label: lathe::nodes::start to My LLM Step
| Field | Type | Description |
|---|---|---|
from / to |
string | Must match an id in nodes. |
label |
string | A human-readable description of the edge — purely descriptive, it doesn't affect execution. |
Execution order is derived from the graph's topology (a topological sort), not from the order connections appear in the file. A node with multiple outgoing connections fans out to multiple downstream nodes; a node with multiple incoming connections fans in from multiple upstream nodes. See Examples § Explainer agent for a worked fan-out pipeline.
Provider Configs¶
A map from an arbitrary id to a provider configuration:
provider_configs:
my-openai-config:
id: my-openai-config
provider: OpenAI
api_key: null
base_url: null
| Field | Type | Description |
|---|---|---|
id |
string | Must match the map key. Referenced by LLMNode.provider_config_id. |
provider |
OpenAI | LMStudio |
Which provider this config is for. |
api_key |
string or null |
API key. For OpenAI, null falls back to the OPENAI_API_KEY environment variable. LMStudio doesn't require a key. |
base_url |
string or null |
API endpoint. null uses the provider's default: OpenAI's standard endpoint for OpenAI, or http://localhost:1234/v1 for LMStudio. |
Tools¶
The top-level tools map declares tools that LLMNodes can be given access to, keyed by an arbitrary id that LLMNode.tools entries reference:
tools:
geocode-tool:
kind: HttpRequest
name: geocode-tool
description: Look Up City Coordinates in Latitude and Longitude
method: GET
url: https://nominatim.openstreetmap.org/search?city={{city}}&format=json
headers:
User-Agent: lathe-weather-agent/1.0
body: null
timeout: 5000
response_type: Json
params:
city:
type: Text
description: City name to geocode, e.g. 'Chennai'
Each entry is tagged with kind, the same tagged-union pattern as the nodes list's !Start/!LLMNode/!End tags but spelled as a kind field instead of a YAML tag. HttpRequest is currently the only supported kind.
HttpRequest¶
Issues an HTTP request when called, with the LLM's call arguments substituted into url, headers, and body.
| Field | Type | Description |
|---|---|---|
name |
string | Tool name surfaced to the LLM. |
description |
string | Description surfaced to the LLM, used to decide when to call the tool. |
method |
GET | POST | PUT | PATCH | DELETE |
HTTP method to issue. |
url |
string | Request URL. May contain {{param_name}} placeholders — see Param substitution. |
headers |
map of string to string | (optional) Request headers. Values may contain {{param_name}} placeholders and ${ENV_VAR} references. Defaults to empty. |
body |
string or null |
(optional) Request body. May contain {{param_name}} placeholders. Defaults to null. |
timeout |
integer (milliseconds) | (optional) Request timeout. Defaults to 5000. |
response_type |
Json | Text |
How to parse the response body before handing it back to the LLM. |
params |
map | (optional) Named arguments the LLM must supply when calling this tool. Defaults to empty. See below. |
params entries declare the arguments the tool accepts:
params:
city:
type: Text
description: City name to geocode, e.g. 'Chennai'
| Field | Type | Description |
|---|---|---|
type |
Text | Integer | Boolean | Float |
Expected JSON type of the argument. The call fails if the LLM supplies a mismatched type. |
description |
string | Surfaced to the LLM as part of the tool's parameter schema. |
All params are currently required
Every declared param is marked required in the schema surfaced to the LLM, and a call fails if any is missing. There's no way to declare an optional param yet.
Param substitution¶
Wherever {{param_name}} appears in url, a header value, or body, it's replaced with the stringified value the LLM supplied for param_name at call time. A {{...}} placeholder naming something that isn't a declared param is left as-is rather than substituted.
Env vars in headers¶
Independently of param substitution, header values may reference ${ENV_VAR} to pull a secret from the process environment (e.g. an API key you don't want committed to the YAML file):
headers:
Authorization: Bearer ${WEATHER_API_KEY}
This is resolved once, when the graph is loaded — a missing env var fails immediately at load time rather than on first call.
Validation rules¶
Lathe validates a graph when it's loaded (on by default for lathe run and lathe server):
- Every connection's
fromandtomust reference a node that exists innodes. - Every leaf node (no outgoing connections) must be an
Endnode, and everyEndnode must be a leaf node. - A graph must have exactly one
Startnode — none or more than one fails validation. - Every node other than
Startmust have at least one incoming connection; a node with no incoming connection fails validation.
See Concepts § Validation for more on when and why this runs.