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
conversation_starters: # suggested prompts in the UI
- "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:
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
agent's version.
- **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
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
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
`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
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.
@@ -233,15 +245,37 @@ route_after_parse:
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 |
|--------------------|---------------------------------------------------------------|
| `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 |
Exactly one of the two is set per script invocation; **always check both**. The temp
file (when used) is cleaned up automatically after the graph finishes.
Exactly one of the two is set per script invocation; **always check both**.
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
state; the reserved `_next` key is extracted and overrides the default `next`