diff --git a/Graph-Agents.md b/Graph-Agents.md index 0e8e189..e5adc8d 100644 --- a/Graph-Agents.md +++ b/Graph-Agents.md @@ -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_`, exactly like bash tools called by normal + agents. Values may be overridden at runtime via + `loki -a --agent-variable "..."`. 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_` | 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 ...`), 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`