Skip to main content

Workflow Functions

Workflow functions allow you to use Otoroshi workflows as tool function backends. When the LLM decides to call a tool, the gateway executes the referenced workflow with the tool arguments as input and returns the workflow result to the LLM.

This is the most powerful backend kind — workflows can chain HTTP calls, transform data, apply conditional logic, call other LLM providers, query vector stores, and much more.

How it works

  1. The LLM decides to call the tool with structured arguments (e.g., {"query": "latest news"})
  2. The gateway looks up the referenced Otoroshi workflow by ID
  3. The tool arguments are passed as the workflow input (${workflow_input})
  4. The workflow executes its steps (HTTP calls, data transformations, LLM calls, etc.)
  5. The workflow returned value is sent back to the LLM as the tool result

Configuration

{
"name": "my_workflow_tool",
"description": "A tool backed by an Otoroshi workflow",
"strict": true,
"parameters": {
"query": {
"type": "string",
"description": "The search query"
}
},
"required": ["query"],
"backend": {
"kind": "Workflow",
"options": {
"workflow_id": "workflow-entity-id"
}
}
}

Options

ParameterTypeDescription
workflow_idstringThe ID of the Otoroshi workflow entity to execute

Input handling

The tool arguments are passed as the workflow input and accessible via ${workflow_input} in the workflow steps:

  • If the arguments are a JSON object (e.g., {"city": "Paris", "unit": "celsius"}), each key is directly accessible: ${workflow_input.city}, ${workflow_input.unit}
  • If the arguments are a plain string, they are wrapped as {"input": "the string"} and accessible via ${workflow_input.input}

Output handling

The workflow's returned value is serialized to JSON and sent back as the tool result. If the workflow terminates with an error, the error is returned as {"error": ...}.

What are Otoroshi workflows?

Otoroshi workflows are a JSON-based orchestration engine built into Otoroshi. They allow you to build complex automation pipelines using a visual editor or JSON configuration.

A workflow is a directed graph of nodes that execute sequentially or in parallel. Key node types include:

NodePurpose
workflowSequential step execution
callInvoke a function (HTTP, LLM, store, etc.)
assignSet variables in workflow memory
if / switchConditional branching
foreach / map / filterArray iteration and transformation
parallelConcurrent execution
tryError handling
valueReturn a literal value

Built-in functions

Workflows come with 30+ built-in functions including:

  • HTTP: core.http_client — make HTTP requests to external APIs
  • Storage: core.store_get, core.store_set, core.store_del — key-value storage
  • System: core.system_call, core.env_get, core.config_read
  • Workflow: core.workflow_call — call other workflows
  • WASM: core.wasm_call — execute WASM plugins

The LLM extension registers additional workflow functions for AI operations (LLM calls, embeddings, vector store, moderation, etc.).

Basic workflow structure

{
"kind": "workflow",
"steps": [
{
"kind": "call",
"function": "core.http_client",
"args": {
"url": "https://api.example.com/search?q=${workflow_input.query}",
"method": "GET"
},
"result": "api_response"
},
{
"kind": "assign",
"values": {
"formatted_result": {
"$jq": {
"value": { "$mem_ref": { "name": "api_response" } },
"filter": ".body | fromjson | .results"
}
}
}
}
],
"returned": { "$mem_ref": { "name": "formatted_result" } }
}

For full documentation on workflows, see the Otoroshi workflows documentation.

Examples

RAG search tool

A tool that searches a vector store and returns relevant context:

{
"name": "search_knowledge_base",
"description": "Search the knowledge base for relevant information",
"strict": true,
"parameters": {
"query": {
"type": "string",
"description": "The search query"
}
},
"required": ["query"],
"backend": {
"kind": "Workflow",
"options": {
"workflow_id": "workflow_rag_search"
}
}
}

With a workflow that computes embeddings and queries a vector store:

{
"kind": "workflow",
"steps": [
{
"kind": "call",
"function": "extensions.com.cloud-apim.llm-extension.compute_embedding",
"args": {
"provider": "embedding-provider-id",
"input": "${workflow_input.query}"
},
"result": "embedding"
},
{
"kind": "call",
"function": "extensions.com.cloud-apim.llm-extension.vector_store_search",
"args": {
"provider": "vector-store-id",
"vector": { "$mem_ref": { "name": "embedding" } },
"limit": 5
},
"result": "search_results"
}
],
"returned": { "$mem_ref": { "name": "search_results" } }
}

API aggregation tool

A tool that calls multiple APIs and aggregates the results:

{
"name": "get_city_info",
"description": "Get comprehensive information about a city including weather and population",
"strict": true,
"parameters": {
"city": {
"type": "string",
"description": "The city name"
}
},
"required": ["city"],
"backend": {
"kind": "Workflow",
"options": {
"workflow_id": "workflow_city_info"
}
}
}

With a workflow that makes parallel HTTP calls:

{
"kind": "workflow",
"steps": [
{
"kind": "parallel",
"parallels": [
{
"kind": "call",
"function": "core.http_client",
"args": {
"url": "https://api.weather.example.com/v1/weather?city=${workflow_input.city}",
"method": "GET"
},
"result": "weather"
},
{
"kind": "call",
"function": "core.http_client",
"args": {
"url": "https://api.geodata.example.com/v1/city?name=${workflow_input.city}",
"method": "GET"
},
"result": "geo_data"
}
]
},
{
"kind": "assign",
"values": {
"result": {
"weather": { "$mem_ref": { "name": "weather" } },
"geo_data": { "$mem_ref": { "name": "geo_data" } }
}
}
}
],
"returned": { "$mem_ref": { "name": "result" } }
}

LLM sub-call tool

A tool that calls another LLM provider to process data:

{
"name": "summarize_text",
"description": "Summarize a long text into a concise summary",
"strict": true,
"parameters": {
"text": {
"type": "string",
"description": "The text to summarize"
}
},
"required": ["text"],
"backend": {
"kind": "Workflow",
"options": {
"workflow_id": "workflow_summarize"
}
}
}

With a workflow that calls an LLM provider:

{
"kind": "workflow",
"steps": [
{
"kind": "call",
"function": "extensions.com.cloud-apim.llm-extension.llm_call",
"args": {
"provider": "llm-provider-id",
"prompt": "Summarize the following text in 3 sentences:\n\n${workflow_input.text}"
},
"result": "summary"
}
],
"returned": { "$mem_ref": { "name": "summary" } }
}

Provider configuration

Reference workflow-backed tool functions in the provider's wasm_tools array like any other tool function:

{
"provider": "openai",
"connection": {
"base_url": "https://api.openai.com/v1",
"token": "${vault://local/openai-token}",
"timeout": 30000
},
"options": {
"model": "gpt-4o",
"wasm_tools": [
"tool-function_rag_search",
"tool-function_city_info"
],
"max_function_calls": 10
}
}

Comparison with other backends

AspectQuickJsHTTPWorkflow
ComplexitySimple logicSingle API callMulti-step orchestration
CapabilitiesJavaScript + HTTPHTTP request/responseHTTP, LLM, vector store, conditions, loops, parallel execution
Data transformationJavaScript coderesponse_path extractionFull operator library ($jq, $map_get, $projection, etc.)
Error handlingtry/catch in JSHTTP error codestry nodes with error handling steps
Best forQuick data processingCalling a single external APIComplex pipelines, RAG, multi-API aggregation