Skip to content

Variables

Variables are named references that are substituted with values at runtime. SFMD defines the syntax for referencing variables — storage and resolution are handled by the runtime.


SyntaxTypePurpose
{name}Session variableRuntime data flow between actions
$NAMEPersistent variableConfiguration, credentials, settings

{variable_name}

Curly braces around an identifier.

RuleValidInvalid
Lowercase letters{city}
Numbers allowed{temp2}
Underscores allowed{current_temp}
Must start with a letter{token}{2token}

Pattern: \{[a-z][a-z0-9_]*\}

Session variables can appear in:

  • Response templates (assignment and output lines)
  • Action definition URIs and headers
  • Action invocation arguments (AI commands)
{city} = {Response.body.city}
## Weather in {city}
/act.search --city {city}

$VARIABLE_NAME

Dollar sign followed by an identifier.

RuleValidInvalid
Uppercase letters$API_KEY
Numbers allowed$KEY2
Underscores allowed$DEFAULT_REGION
Must start with a letter$TOKEN$2TOKEN
Lowercase allowed$api_key

Pattern: \$[a-zA-Z][a-zA-Z0-9_]*

Convention: uppercase for configuration ($API_KEY), but not enforced.

Persistent variables can ONLY appear in:

  • Action definition blocks (act.name code blocks)
GET https://api.example.com/search?key=$API_KEY

Persistent variables MUST NOT appear in:

  • AI command arguments (use {var} instead)
  • Response template assignments

This keeps a clean separation: $var is wired into action definitions by document developers; AI uses {var} in commands.

When the runtime encounters $NAME in an action definition (URL, headers, or body template), it resolves the value using this cascade:

  1. Per-call extra env — context variables passed programmatically by the caller (tool context vars in tool blocks, etc.).
  2. SFMD env-store — per-user persistent values set via /set NAME = "value". Stored encrypted on disk at ~/.string/config.json.
  3. Daemon process envprocess.env of the running stringd process. Inherits from the shell that started the daemon, so export GEMINI_API_KEY=... && string --daemon start makes the key available to all actions.
  4. Unresolved — if none of the above have a value, the literal $NAME is left in place so the failure is visible (e.g., the API sees $API_KEY as a literal and returns an auth error, which the agent can diagnose).

The process.env fallback (step 3) is a convenience for API keys and configuration that are more naturally managed as shell environment variables than as SFMD-specific /set values. It does NOT expose arbitrary process env to the action — only the specific $NAME referenced in the action definition is resolved. An action that does not reference $HOME never sees $HOME.


Variables are assigned in response templates:

{variable} = {expression}
  1. Assignment is a full line: {id} = {expression}.
  2. Left side MUST be a session variable: {name}.
  3. Right side is an expression that resolves to a value.
  4. Assignment lines produce no output.
  5. Only {variables} can be assigned. $variables cannot.
ExpressionMeaning
{Response.body.field}Value from action response
{Response.body.nested.field}Nested response value
{Response.status}HTTP status code
"literal"Literal string value
{other_variable}Value of another variable
{city} = {Response.body.city}
{temp} = {Response.body.temperature}
{status} = {Response.status}
{label} = "default"

Variables in output lines are substituted with their values:

## Weather in {city}
- Temperature: {temp}°C

If a variable has no value, the reference is left as-is or replaced with an empty string (runtime-dependent).


Variable typeScope
{variable}Topic session — each topic has its own set
$VARIABLEPer-user persistent — with cascade (config > app > global)

Session variables in a topic override persistent variables of the same name within that topic’s scope.


  1. Session variables: {name}[a-z][a-z0-9_]* in curly braces.
  2. Persistent variables: $NAME[a-zA-Z][a-zA-Z0-9_]* with $ prefix.
  3. {var} can appear in templates, invocations, and action definitions.
  4. $VAR can ONLY appear in action definition blocks (URL, headers, body template).
  5. $VAR resolution cascade: per-call extra env → SFMD env-store → daemon process.env → unresolved literal.
  6. Assignment: {var} = {expression} — full line, no output.
  7. Only {var} can be on the left side of assignment.
  8. {var} is session-scoped. $VAR is persistent per-user (with process.env fallback).
  9. Topic {var} overrides $VAR of the same name in that scope.
  10. Response paths support dot-and-bracket notation: body.items[0].name.