Output Modes
Operations behave differently depending on whether they have a returns: key. This determines how output is handled and displayed.
The Two Modes
Script Mode (without returns:)
Operations without returns: behave like shell scripts - all command stdout goes to stdout:
dyngle:
operations:
build:
- echo "Starting build..."
- npm install
- npm run build
- echo "Build complete!"
All output is visible, making these ideal for build, deploy, and other workflow tasks where you want to see progress.
Function Mode (with returns:)
Operations with returns: behave like functions - command stdout is suppressed, and only the return value is provided as output:
dyngle:
operations:
get-temperature:
returns: temp
steps:
- echo "Fetching weather..." # stdout suppressed
- curl -s "https://api.example.com/weather" => weather-data
- weather-data -> jq -r '.temperature' => temp
Only the return value is output, making these ideal for data queries and transformations.
Important:
- stderr is always displayed in both modes
- The
=>operator works in both modes (capturing stdout to a variable)
Output Destinations
Where the output goes depends on how the operation is invoked.
In the run Command
When running an operation with dyngle run, output goes to stdout.
Script mode - All command stdout is displayed:
dyngle run build
Output:
Starting build...
[npm install output...]
[npm run build output...]
Build complete!
Function mode - Only the return value is displayed:
dyngle run get-temperature
Output:
72
Output formatting depends on the return value type:
- Simple types (strings, numbers, booleans) - Printed as-is
- Dictionaries and lists - Formatted as YAML
Example with structured data:
dyngle:
operations:
get-user:
returns: user
steps:
- curl -s "https://api.example.com/user/123" => user
dyngle run get-user
Output:
name: Alice Smith
email: [email protected]
role: admin
In Sub-operations
When an operation is called as a sub-operation, its return value is captured by the parent's receive: attribute:
dyngle:
operations:
get-version:
returns: version
steps:
- cat package.json -> jq -r '.version' => version
tag-release:
steps:
- sub: get-version
receive: ver
- git tag "v{{ver}}"
- git push origin "v{{ver}}"
The return value becomes a variable in the parent operation's context.
If no returns: is specified, receive: captures None.
In the MCP Server
When operations are exposed via the MCP server, they return JSON responses.
Success with return value:
dyngle:
operations:
get-weather:
description: Get current weather for a city
returns: weather-info
accepts:
city: { type: string }
steps:
- curl -s "https://api.example.com/weather?city={{city}}" => weather-info
Response:
{
"result": {
"temperature": 72,
"conditions": "Sunny",
"humidity": 65
}
}
Success without return value:
dyngle:
operations:
run-backup:
description: Run the nightly backup process
steps:
- /usr/local/bin/backup.sh
Response:
{
"result": null
}
Error:
{
"error": "Operation failed: command not found"
}
This makes operations with return values particularly useful as AI assistant tools - they can return structured data that assistants can incorporate into responses.
Specifying Return Values
Use the returns: key to specify what value to return:
dyngle:
operations:
get-temperature:
returns: temp
steps:
- curl -s "https://api.example.com/weather" => weather-data
- weather-data -> jq -r '.temperature' => temp
The returns: key can reference anything in the operation context using context paths:
- Variables (set via
=>orreceive:) - Constants (from
constants:) - Expressions (from
expressions:) - Inputs (from stdin,
send:, or MCP) - Nested properties (using dot-separated context paths)
Examples:
dyngle:
operations:
# Return a variable
fetch-data:
returns: data
steps:
- curl -s "https://api.example.com" => data
# Return a constant
get-env:
returns: environment
constants:
environment: production
# Return an expression
get-timestamp:
returns: timestamp
expressions:
timestamp: "dtformat(datetime.now(), '%Y-%m-%d %H:%M:%S')"
# Return nested property
get-host:
returns: config.server.host
constants:
config:
server:
host: api.example.com
port: 443
Display Control
The --display option controls whether step commands are shown before execution, independently of output mode:
dyngle run build --display none
This suppresses step display but doesn't affect the mode (script vs function) or stdout handling.
See CLI Commands for details on the --display option.
Examples
Simple String Return
dyngle:
operations:
get-version:
returns: version
steps:
- cat package.json -> jq -r '.version' => version
dyngle run get-version
Output:
1.2.3
Structured Data Return
dyngle:
operations:
system-info:
returns: info
expressions:
info:
hostname: "get('runtime.args.0') or 'localhost'"
timestamp: "datetime.now()"
user: "'admin'"
dyngle run system-info myserver
Output:
hostname: myserver
timestamp: 2024-12-14 22:00:00
user: admin
Computed Return Value
dyngle:
operations:
calculate-total:
returns: total
steps:
- curl -s "https://api.example.com/items" => items
- items -> jq '[.[] | .price] | add' => total
Workflow with No Return
dyngle:
operations:
deploy:
description: Deploy to production
steps:
- echo "Starting deployment..."
- sub: build
- aws s3 sync ./dist s3://my-bucket/
- echo "Deployment complete!"
All output is visible during execution.
Best Practices
Use Function Mode for Data Operations
Operations that query or transform data should use returns::
dyngle:
operations:
get-status:
description: Check deployment status
returns: status
steps:
- curl -s "https://api.example.com/status" => status
Use Script Mode for Workflows
Operations that perform tasks should omit returns::
dyngle:
operations:
deploy:
description: Deploy application
steps:
- sub: build
- sub: test
- sub: upload
- echo "Deployment complete!"
Return Structured Data for MCP
Operations exposed via MCP should return meaningful structured data:
dyngle:
operations:
check-health:
description: Check application health
returns: health
steps:
- curl -s "https://api.example.com/health" => health
This allows AI assistants to understand and use the returned information.