Generate Your Own Nyno Workflow Extensions
Generate Your Own Nyno Workflow Extensions (Markdown Version)
Nyno Extension Rules (Simple)
1. Basic Rules
- Extensions are single workflow steps.
- Receive
args(simple array/list) andcontext(key-values). - Can read or modify any context variable.
- Default output is stored in
context[set_context], whereset_contextdefaults to"prev". - For API keys, use
context, for example VENDOR_NAME_API_KEY, never use api keys inargs.
2. Dynamic Output Key
-
To customize output, use the
set_contextkey incontext. -
If
set_contextis not provided, it defaults to"prev". -
Example:
const setName = context?.set_context ?? "prev"; context[setName] = result; -
This allows the workflow to store results under a custom context variable or reuse the previous step’s output.
3. Return Values
-
Must return an integer:
0= success- -1 = error
1/other number= for very rare cases with clear different branches
4. Context Usage
-
Extensions may store or overwrite data in context.
-
Context can pass global values (API keys, URLs, etc.) to other steps.
-
Errors can also be stored dynamically using the same
set_contextvalue:context[setName + "_error"] = { errorMessage };
5. Syntax
- Follow language-specific function signatures (JS (Use ES6 import/exports only, named function export, no module.exports), Python, PHP, Ruby).
- Only use
argsandcontext. - Always prefix the function with
nyno_if no other prefix is provided.
6. Language Choice Guideline
- Choose the language that best fits the task.
- Prefer the language with the strongest or most mature library support for what you need (e.g. APIs, SDKs, file formats, ML, scraping).
- Performance, ecosystem, and developer ergonomics are valid reasons to choose one language over another.
- If JS, always use ES6 with imports not requires.
7. Examples
Example Python extension
# extensions/hello-py/command.py
def hello_py(args, context):
name = args[0] if args else "World"
set_name = context.get("set_context", "prev")
context[set_name] = f"Hello, {name} from Python!"
return 0
Example PHP extension
<?php
// extensions/hello-php/command.php
function hello_php($args, &$context) { // & required to modify context
$name = $args[0] ?? "World";
$setName = $context["set_context"] ?? "prev";
$context[$setName] = "Hello, $name from PHP!";
return 0;
}
Example Ruby extension
# extensions/hello-rb/command.rb
def hello_rb(args, context)
name = args[0] || "World"
set_name = context["set_context"] || "prev"
context[set_name] = "Hello, #{name} from Ruby!"
return 0
end
JS Example using context to pass data between steps
export function some_extension(args, context) {
const result = args[0] || "default value";
const setName = context?.set_context ?? "prev";
// Save output in context for the next step
context[setName] = result;
return 0; // default path
}
8. Libraries
- In JS, never use Axios, use the build in fetch (we run the latest nodejs).
- Prefer direct HTTP requests/Linux commands over libraries/sdks unless explicitly asked.
9. Security
- Prevent RCE: If you need to use linux commands, always use the list input so variables are escaped, never use raw shell concatination.
- Prevent Path Traversal: If an argument is about a relative path with another directory as base, then alwas check if the path resolved to a path that starts with the base.
- Prevent SQL injection: always use prepared statements for args/user input variables.
- Overall just use the best security practices, especially when dealing with user input variables.