Declarative YAML workflow engine for AI pipelines — run multi-step LLM chains with branching, guardrails, retry, and observability out of the box.
python3.11 --version)python3.11 -m pip --version)bash
export GEMINI_API_KEY="your-key"
bash
python3.11 -m pip install "beddel[all]"
beddel version
Note: System Python may be 3.10. Always use
python3.11explicitly.
hello.yaml:yaml
id: hello
name: Hello World
input_schema:
topic: { type: str, required: true }
steps:
- id: greet
primitive: llm
config:
model: gemini/gemini-2.0-flash
prompt: "Write a one-sentence greeting about $input.topic"
max_tokens: 50
bash
beddel run hello.yaml -i topic="AI agents" --json-output
The beddel tool is available via the OpenClaw plugin @botanarede/beddel:
bash
openclaw plugins install @botanarede/beddel
Once installed, the agent can invoke beddel with actions: run, validate, list-primitives.
The bundled example examples/setup-beddel.yaml automates this installation — see Bundled Example below.
CommandDescriptionbeddel run <file> [-i key=val] [--json-output]Execute a workflowbeddel validate <file>Validate YAML syntax and schemabeddel list-primitivesShow available primitivesbeddel serve -w <file> [--port 8000]Serve workflow as HTTP endpointbeddel versionPrint installed version
A workflow is a YAML file with an id, name, optional input_schema, and a list of steps. Each step declares a primitive (the unit of work) and a config (primitive-specific parameters).
Steps execute sequentially. Each step's output is available to subsequent steps via $stepResult.<step_id>.<path>.
See references/ for full schema documentation.
PrimitivePurposellmSingle-turn LLM call with streaming supportchatMulti-turn conversation with message historyoutput-generatorTemplate-based output rendering (JSON, Markdown, text)guardrailData validation with strategies: raise, return_errors, correct, delegatecall-agentNested workflow invocation with depth trackingtoolExternal function call — shell_exec is built-inagent-execUnified adapter for external agent delegation
Each step can declare an execution_strategy to control error handling:
StrategyBehaviorfailStop workflow on error (default)skipLog error, continue to next stepretryRetry with exponential backoff and jitterfallbackExecute an alternative step on failuredelegateDelegate error recovery to agent judgment
NamespaceExampleSource$input``$input.topicRuntime inputs ( -i key=val)$stepResult``$stepResult.greet.contentPrevious step outputs$env``$env.GEMINI_API_KEYEnvironment variables
Key paths for step results:
$stepResult.<id>.result.stdout, .result.exit_code$stepResult.<id>.content$stepResult.<id>.data.<field>, .validThis workflow checks whether the @botanarede/beddel OpenClaw plugin is installed and installs it if needed. It demonstrates 3 of the 7 primitives: tool, guardrail, and conditional execution via if.
yaml
id: setup-beddel
name: Beddel Plugin Setup
description: Install or update the @botanarede/beddel OpenClaw plugin and verify it loads.
steps:
- id: check_plugin
primitive: tool
config:
tool: shell_exec
arguments:
cmd: "python3.11 -c \"import subprocess,json,re;r=subprocess.run(['openclaw','plugins','list'],capture_output=True,text=True);has=bool(re.search(r'beddel',r.stdout));loaded=bool(re.search(r'beddel.*loaded',r.stdout));print(json.dumps({'action':'OK'if loaded else'REINSTALL'if has else'INSTALL'}))\""
- id: validate_check
primitive: guardrail
config:
data: "$stepResult.check_plugin.result.stdout"
schema:
fields:
action: { type: str, required: true }
strategy: correct
- id: install_plugin
primitive: tool
config:
tool: shell_exec
arguments:
cmd: "openclaw plugins install @botanarede/beddel"
timeout: 120
if: "$stepResult.validate_check.data.action != 'OK'"
- id: verify
primitive: tool
config:
tool: shell_exec
arguments:
cmd: "openclaw plugins info beddel"
StepPrimitiveFeaturecheck_plugin``toolDeterministic check via shell_exec — outputs JSON without LLMvalidate_check``guardrail``correct strategy — parses JSON string, strips markdown fences, validates schemainstall_plugin``toolConditional execution ( if) — skips when plugin already loaded. timeout: 120 for network opsverify``toolPost-install verification
Run it:
bash
beddel run examples/setup-beddel.yaml --json-output
$env.* variables — never hardcode API keys in workflow YAMLshell=False (no shell injection). Commands are split via shlex.split(). Shell operators ( |, &&, >) are sanitized in beddel 0.1.1+EndpointWhenPurposeLLM provider API (e.g. generativelanguage.googleapis.com)llm, chat, guardrail (delegate) stepsModel inferencePyPI ( pypi.org)Installation onlyPackage downloadnpm registry ( registry.npmjs.org)Plugin install stepPlugin download
Beddel executes user-defined YAML workflows. It does not phone home, collect telemetry by default, or transmit data beyond the configured LLM provider endpoints. OpenTelemetry export is opt-in.
Beddel emits OpenTelemetry spans for every workflow and step execution:
beddel.workflow.execute — root span per workflow runbeddel.step.<primitive> — child span per stepgen_ai.usage.* attributes on LLM steps (prompt/completion tokens)Enable with any OTel-compatible collector via standard OTEL_* environment variables.
ErrorCauseFixBEDDEL-PRIM-300Tool not foundEnsure tool name is shell_exec (built-in). Custom tools need -t name=module:func``BEDDEL-RESOLVE-001Unresolvable variableCheck step id spelling and result path. Tool results use .result.stdout, LLM uses .content``BEDDEL-GUARD-201Guardrail validation failedCheck schema field types. Use strategy: correct for JSON string inputspython3.11: not foundWrong Python versionInstall Python 3.11+. System Python may be 3.10Step shows SKIPPED``if condition was false or execution_strategy: skipExpected behavior — downstream steps should handle SKIPPED values
python
from beddel import WorkflowExecutor, VariableResolver
resolver = VariableResolver()
resolver.register_namespace("secrets", lambda path, ctx: get_secret(path))
executor = WorkflowExecutor(resolver=resolver)
result = await executor.execute(workflow, {"topic": "AI"})
For FastAPI integration: beddel serve -w workflow.yaml --port 8000
Additional documentation in references/ (loaded on demand):
workflow-format.md — Complete YAML schemaprimitives.md — All 7 primitives with full config optionsexecution-strategies.md — 5 strategies with examplesvariable-resolution.md — Namespaces, custom resolvers, error handling