klieo-workflow 3.8.1

Declarative no-code workflow substrate for the klieo agent framework.
Documentation
# klieo-workflow

Declarative no-code workflow substrate for the klieo agent framework.

Part of the [klieo](https://crates.io/crates/klieo) Rust agent framework.

Author an agent workflow as data (a `WorkflowDef`, typically JSON emitted by a
visual builder) and lower it into a runnable `klieo_flows::Flow` with
`compile` — no Rust compile step per workflow.

## Usage

```toml
[dependencies]
klieo-workflow = "3"
```

Via the umbrella crate:

```toml
[dependencies]
klieo = { version = "3", features = ["workflow"] }
```

## Envelope model

State is a single shared JSON **object** — the *envelope* — threaded through
every node. Each node reads one named field (`input_from`) as its input and
writes its result to another named field (`output_to`), returning the whole
envelope. Downstream nodes read the fields their predecessors wrote. The
compiled flow rejects a non-object run input with a typed error rather than
silently coercing it.

## Node palette

| `kind` | Runs | Fields |
|--------|------|--------|
| `agent` | A data-configured `SimpleAgent` against a registered model | `agent: { model, system_prompt, tools? }` |
| `tool` | A registered tool, dispatched by id through the context | `tool: <id>` |
| `subflow` | A prebuilt `Flow` registered under an id | `ref: <id>` |

Every node also carries `input_from` / `output_to` (agent and tool nodes).

## The Registry is the authorization boundary

`compile` validates a `WorkflowDef` against a `Registry` — the allow-list of
primitives a workflow may reference. A model id must be registered
(`with_model`), a tool id must be allowed (`with_tool`), and a subflow id must
be registered (`with_subflow`). Anything a def references that is not in the
registry is rejected at compile time with a typed `CompileError`. This is the
authorization boundary for no-code workflows: authoring data cannot reach a
primitive an operator did not register.

## Linear example

```json
{
  "id": "greet",
  "entry": "greet",
  "nodes": [
    { "id": "greet", "kind": "agent", "input_from": "q", "output_to": "r1",
      "agent": { "model": "default", "system_prompt": "Greet the user." } },
    { "id": "elaborate", "kind": "agent", "input_from": "r1", "output_to": "r2",
      "agent": { "model": "default", "system_prompt": "Add a follow-up." } }
  ],
  "edges": [ { "from": "greet", "to": "elaborate" } ]
}
```

## Branching example

An edge is either unconditional (`to`) or conditional (`when` → `then` /
`else`); the two forms are mutually exclusive. A `when` is a bounded
comparison (`eq | ne | gt | gte | lt | lte | exists | contains`) over one
envelope field.

```json
{
  "id": "triage",
  "entry": "score",
  "nodes": [
    { "id": "score", "kind": "subflow", "ref": "risk_scorer" },
    { "id": "review", "kind": "subflow", "ref": "human_review" },
    { "id": "approve", "kind": "subflow", "ref": "auto_approve" }
  ],
  "edges": [
    { "from": "score",
      "when": { "field": "risk", "op": "gte", "value": 0.8 },
      "then": "review", "else": "approve" }
  ]
}
```

## Limits

- No human-in-the-loop, loop, or parallel node kinds; the palette is
  `agent | tool | subflow`.
- At most one outgoing edge per node.
- A per-node model must be registered in the `Registry`; there is no implicit
  default model.
- The top-level run input must be a JSON object.

## License

MIT