Workflow
The Workflow guardrail lets you use an Otoroshi workflow to validate messages. This is similar to the WASM and QuickJS guardrails, but instead of writing code in a specific language, you define the validation logic as an Otoroshi workflow — a visual, composable pipeline of steps.
This is ideal when your validation logic requires orchestrating multiple steps (e.g., calling an external API, then checking the result against a database, then applying business rules).
It can be applied before sending the prompt to the LLM and after to validate the LLM response.
How it works
- The guardrail loads the workflow referenced by its ID from Otoroshi's workflow registry
- It executes the workflow with an input payload containing the messages, configuration, provider info, and request attributes
- The workflow must return a JSON object with a
passfield (trueorfalse) and an optionalreasonfield explaining a denial
Configuration
The following configuration has to be placed in your LLM provider entity in the Guardrail Validation section.
"guardrails": [
{
"enabled": true,
"before": true,
"after": true,
"id": "workflow",
"config": {
"workflow_id": "workflow_xxxxxxxxx"
}
}
]
Field explanations
- enabled:
true— The guardrail is active - before:
true— The guardrail applies to user input before sending to the LLM - after:
true— The guardrail applies to the LLM response
Config section
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
workflow_id | string | Yes | — | Reference ID of the workflow to execute. Can also be specified as workflow_ref. |
Workflow input
The workflow receives the following JSON object as input:
{
"config": {
"workflow_id": "workflow_xxxxxxxxx"
// ... any additional config fields
},
"provider": { /* provider config or null */ },
"attrs": { /* request attributes */ },
"messages": [
{ "role": "user", "content": "the user message" },
{ "role": "assistant", "content": "the assistant response" }
]
}
Expected workflow output
The workflow must return a JSON object with the following structure:
| Output | Result |
|---|---|
{"pass": true} | Message passes |
{"pass": false, "reason": "explanation"} | Message is denied with a custom reason |
If the workflow returns {"pass": false} without a reason, the default denial message is:
message blocked by workflow guardrail
If the workflow fails with an error, the guardrail returns an error result with the workflow error details.
Use cases
- Multi-step validation — Chain multiple checks (regex, API calls, database lookups) in a single guardrail
- Business rules — Implement complex, organization-specific policies that go beyond simple pattern matching
- External integrations — Call external services (compliance APIs, content moderation services) as part of the validation
- Conditional logic — Apply different validation rules based on message metadata, user context, or other dynamic factors
When to use this vs WASM/QuickJS
| Workflow | WASM | QuickJS | |
|---|---|---|---|
| Complexity | Visual pipeline, no code | Compiled code (Rust, Go, etc.) | JavaScript code |
| Best for | Multi-step orchestration | High-performance validation | Simple scripted validation |
| External calls | Native support | Requires WASI networking | Limited |
| Reusability | Workflows are reusable entities | Plugins are reusable | Scripts via URL |