ifURI examples
← all examples

23 — self-repairing LLM flow over llm://

Talk to an LLM through the llm:// connector (you pick the model and the provider), have it emit a YAML flow, run that flow through urirun, and — if a step fails — feed the step + error back to the model so it returns a corrected flow. Repeat until it runs or the attempt budget is spent.

action space (URIs + schemas)
        │
        ▼
llm://host/chat/command/complete   ──▶  YAML flow
        ▲                                   │
        │ failing step + error              ▼
        └────────── urirun runs each step under policy ──▶ ok → done

Model + provider selection (on the llm:// payload)

llm://host/chat/command/complete takes {prompt, model, base_url}:

(http://localhost:11434, which serves /api/generate). Point it at a litellm / OpenAI-compatible proxy to use hosted models (Claude, GPT, …): the proxy is the provider, model selects which model behind it.

# local Ollama
python3 repair_flow.py "stamp the current time" --model llama3 --base-url http://localhost:11434

# hosted model via a litellm proxy (the proxy is the provider)
python3 repair_flow.py "stamp the current time" \
    --model claude-3.5-sonnet --base-url http://localhost:4000

The flow's action space here is the time-tools connector; swap tt.conn.registry() in repair_flow.py:main for your own set (or urirun.entry_point_registry() for every installed connector).

The loop (generate_run_repair)

  1. urirun.action_space(registry) → the routes + input schemas the model may use.
  2. ask_llm() calls llm:// → raw reply → _extract_yaml() strips ``` fences.
  3. run_flow() runs each step with urirun.run(..., mode="execute", policy=urirun.policy(allow=...)),

unwraps the result via urirun.result_data(env), stops on the first failure.

  1. On failure the next prompt includes the failing step + error + the previous

YAML, so the model returns a fix. Loops up to --max-attempts.

Safety is urirun's: query routes run freely, command routes only under the --allow policy; secrets stay deny-by-default.

Run on a remote mesh node (repair_flow_mesh.py)

The brain (LLM) runs locally; the generated flow executes on a remote urirun node over HTTP. The action space comes from the node's /routes, each step is forwarded with urirun.runtime.v2_service.call (POST {node}/run, via URI_SERVICE_MAP), and the node's own --allow is the security boundary.

export URIRUN_MESH_CONFIG=~/.urirun-host/mesh.json   # set up by the host installer

# dry-run: generate + validate the flow against the node's schemas, do NOT execute
python3 repair_flow_mesh.py --node officepc --dry-run "report runtime health and the OS name"

# execute on the node
python3 repair_flow_mesh.py --node officepc "report runtime health and write an audit log line"

OpenRouter / hosted models via examples/.env

The llm:// connector talks Ollama's /api/generate, so for OpenRouter / OpenAI / Anthropic use the litellm path (--litellm), which picks the provider from the model prefix (openrouter/…, openai/…, anthropic/…, ollama/…) plus the matching *_API_KEY. The repo's examples/.env already carries both:

OPENROUTER_API_KEY=sk-or-...
LLM_MODEL=openrouter/google/gemini-3.1-flash-image-preview

--env-file loads it and uses LLM_MODEL as the model:

# dry-run a flow on the remote node, generated by an OpenRouter model:
python3 repair_flow_mesh.py --litellm --env-file ../.env \
    --node officepc --dry-run \
    "check whether git and docker are installed, report the OS, and log the audit"

# then execute it for real on the node:
python3 repair_flow_mesh.py --litellm --env-file ../.env \
    --node officepc \
    "report runtime health and current date, then write a log entry that the audit ran"

Verified live against a node (lenovo, 7 safe routes): the OpenRouter model emitted a schema-valid flow on the first attempt and it ran on the node — report ok: True, attempts: 1, returning the node's real platform / date and writing the log entry. Override the model per run with --model openrouter/<vendor>/<model> (or --model ollama/llama3 --base-url http://localhost:11434 for local, without --litellm).

Test (offline, no model needed)

A fake LLM returns a broken flow first (unknown route), then — once the error is fed back — a valid one, proving the repair loop end-to-end. test_repair_mesh.py does the same against a fake in-process HTTP node (forward + repair), so no model and no remote machine are needed:

pytest -q          # test_repair.py (local) + test_repair_mesh.py (mesh) — 4 passed

Files

.gitignoreREADME.mdrepair_flow.pyrepair_flow_mesh.pytest_repair.pytest_repair_mesh.py.benchmarks/

View on GitHub →