docs: added environment variable documentation for script nodes

2026-05-21 13:31:58 -06:00
parent 732d43e298
commit a0fda62bb4
+38 -4
@@ -70,6 +70,10 @@ mcp_servers: # MCP servers available to nodes
- pubmed-search - pubmed-search
conversation_starters: # suggested prompts in the UI conversation_starters: # suggested prompts in the UI
- "Research WebAssembly outside of the browser" - "Research WebAssembly outside of the browser"
variables: # optional; agent variables
- name: project_dir # exposed to script nodes as
description: Project root # LLM_AGENT_VAR_PROJECT_DIR, overridable
default: "." # via `--agent-variable` at runtime
settings: settings:
max_loop_iterations: 100 # PER-NODE visit cap; default 100 (see below) max_loop_iterations: 100 # PER-NODE visit cap; default 100 (see below)
@@ -96,13 +100,21 @@ nodes:
else fails at startup. This is the *graph schema* version, not your else fails at startup. This is the *graph schema* version, not your
agent's version. agent's version.
- **Agent-level config** (`model`, `temperature`, `top_p`, `global_tools`, - **Agent-level config** (`model`, `temperature`, `top_p`, `global_tools`,
`mcp_servers`, `conversation_starters`) are all optional. `mcp_servers`, `conversation_starters`, `variables`) are all optional.
These are the same fields a normal agent's `config.yaml` carries; in a These are the same fields a normal agent's `config.yaml` carries; in a
graph agent they live at the top of `graph.yaml` instead. `model` / graph agent they live at the top of `graph.yaml` instead. `model` /
`temperature` / `top_p` act as the defaults for `llm` nodes that don't `temperature` / `top_p` act as the defaults for `llm` nodes that don't
set their own. `global_tools` and `mcp_servers` define the tool universe set their own. `global_tools` and `mcp_servers` define the tool universe
that an `llm` node's `tools:` whitelist selects from (a node with no that an `llm` node's `tools:` whitelist selects from (a node with no
`tools:` field gets none of them). `tools:` field gets none of them).
- **`variables`:** Same shape as a normal agent's `variables:` block.
Each declared variable becomes available to script nodes as the env var
`LLM_AGENT_VAR_<UPPER_NAME>`, exactly like bash tools called by normal
agents. Values may be overridden at runtime via
`loki -a <agent> --agent-variable <name> <value> "..."`. For LLM nodes to
see a variable inside prompts, seed its value into state (typically via
a setup script that reads the env var and writes it into state) so
`{{name}}` resolves.
- **`can_spawn_agents` is derived, not declared.** A graph agent can spawn - **`can_spawn_agents` is derived, not declared.** A graph agent can spawn
child agents iff its graph contains at least one `agent` node. You don't child agents iff its graph contains at least one `agent` node. You don't
set a flag. The `agent` node's presence *is* the declaration. set a flag. The `agent` node's presence *is* the declaration.
@@ -233,15 +245,37 @@ route_after_parse:
last_run: "{{some_value}}" last_run: "{{some_value}}"
``` ```
The script receives the current state in two forms; use whichever fits: ### Environment
The script receives the current graph state in one of two forms (use whichever fits):
| Env var | Contents | | Env var | Contents |
|--------------------|---------------------------------------------------------------| |--------------------|---------------------------------------------------------------|
| `GRAPH_STATE` | Inline JSON when serialized state is <= 32 KiB | | `GRAPH_STATE` | Inline JSON when serialized state is <= 32 KiB |
| `GRAPH_STATE_FILE` | Path to a temp JSON file when serialized state exceeds 32 KiB | | `GRAPH_STATE_FILE` | Path to a temp JSON file when serialized state exceeds 32 KiB |
Exactly one of the two is set per script invocation; **always check both**. The temp Exactly one of the two is set per script invocation; **always check both**.
file (when used) is cleaned up automatically after the graph finishes. The temp file (when used) is cleaned up automatically after the graph finishes.
Script nodes also receive the same environment that custom agent tools get when called
from normal agents:
| Env var | Contents |
|--------------------------|----------------------------------------------------------------|
| `LLM_ROOT_DIR` | Loki config dir (e.g. `~/.config/loki`) |
| `LLM_PROMPT_UTILS_FILE` | Absolute path to `.shared/prompt-utils.sh` |
| `LLM_AGENT_DATA_DIR` | The agent's own data directory (where this `graph.yaml` lives) |
| `LLM_AGENT_VAR_<NAME>` | One per declared `variables:` entry; uppercased name |
| `PATH` | Loki's functions bin dir prepended to the inherited `PATH` |
| `CLICOLOR_FORCE`, `FORCE_COLOR` | Both set to `1` so child tools emit ANSI colors |
The script's **working directory** is the loki invocation directory (where
the user ran `loki -a <agent> ...`), not the agent directory. This matches
the behavior of bash tools called by normal agents, and lets scripts use
`"."` or relative paths to refer to the user's project. To resolve sibling
files inside the agent directory (for example `.shared/utils.sh`), use
`"$(dirname "$0")"` from inside the script. Note that`$0` is an absolute path to
the script file itself.
The script must print a single JSON object on stdout. All keys merge into The script must print a single JSON object on stdout. All keys merge into
state; the reserved `_next` key is extracted and overrides the default `next` state; the reserved `_next` key is extracted and overrides the default `next`