Provider-agnostic glue between natural language and validated URML programs.
Project description
A small, opinionated, human-readable language for describing robot intent.
LLM Bridge
Status: 0.1.0, aligned with the other four packages. Shipped: the provider-agnostic Bridge + bounded validator-feedback revision loop, real Anthropic / OpenAI adapters (lazy-imported) + the hermetic EchoProvider, the urml translate / urml emit-prompt CLI, and profile-scoped few-shot libraries (home / industrial / drone). The normative contract is spec/layer-4-nl-grammar/v0.1.0.md; a hermetic end-to-end walkthrough is docs/demos/bridge-roundtrip.md.
What this is
The provider-agnostic glue between natural-language input and a validated URML program. The LLM bridge:
- Takes a natural-language request from a user (or another system).
- Prompts a configured LLM with the Layer-4 prompt contract, the connected robot's Layer-1 capability manifest, and the active safety envelope.
- Receives the LLM's emission (a URML program).
- Calls the validator to statically verify the emission.
- On rejection, surfaces the structured error back to the LLM and requests a revision. Repeats up to a configured bound.
- On acceptance, hands the validated program to the runtime for execution.
- When the request needs a capability the manifest does not declare, the model emits a
report(status: failure)naming what is missing rather than fabricating capability. (An interactive clarifying-question protocol is not in v0.1 — seespec/layer-4-nl-grammar/v0.1.0.md§5.)
Provider neutrality is non-negotiable
URML's value as a standard depends on Layer 4 being provider-neutral. The LLM bridge must support, as first-class citizens:
- Anthropic (Claude family).
- OpenAI (GPT family).
- Open-weights models (Llama, Mistral, Qwen, and their successors), via local serving (vLLM, llama.cpp, Ollama) or hosted inference providers.
- On-device models for offline-capable deployments.
Adding a new provider must be a small adapter in providers/, not a structural change to the bridge. If a provider's particular feature would let URML produce better URML, the bridge surfaces the feature behind a profile-neutral abstraction — never by privileging that provider.
Vendor lock-in here is explicitly prohibited by CLAUDE.md §What Claude Should Never Do.
What the bridge does NOT do
- It does not include or embed any specific LLM provider's API client as a hard dependency. Provider clients are optional and pluggable.
- It does not require cloud connectivity. A deployment using a local open-weights model runs offline end to end.
- It does not persist user inputs, model outputs, or any other data without explicit, opt-in, documented purpose. Trust is the most valuable asset of this project; the bridge will not be the place it leaks.
- It does not execute URML. That is the runtime's job.
- It does not make safety decisions. The validator is the safety boundary; the bridge only relays.
Architecture (planned)
┌────────────────────────┐
user / NL │ LLM Bridge │ validated URML
─────────────▶ • build prompt ├──────────────────▶ runtime
│ • call provider │
│ • validate emission │
│ • revise loop │
└──┬──────────────────▲──┘
│ │
▼ │
providers/ validator
(anthropic.py, (separate
openai.py, process)
local_vllm.py,
on_device.py)
The bridge is small. The intelligence lives in the LLM (which is configured, not built here) and in the validator (which is a separate process). The bridge orchestrates.
Language
- Python.
mypy --strict. Public API fully type-annotated.
API (sketch)
from urml.llm_bridge import Bridge
bridge = Bridge(
provider="anthropic", # or "openai", "vllm", "ollama", ...
spec_versions={...},
manifest=manifest,
envelope=envelope,
profiles=("home",),
max_revisions=3,
)
result = bridge.translate("Bring me the red mug from the kitchen.")
if result.accepted:
runtime.execute(result.program)
else:
# After max_revisions, structured errors surface to the caller.
show_user(result.user_message, result.errors)
Conformance contract
The bridge has its own conformance bar: for the published few-shot example library, the bridge produces accepted URML at or above a stated success rate (per-provider, declared in the bridge's release notes). The conformance suite includes these end-to-end fixtures.
Core Commitment
The LLM bridge — the bridge logic and the prompt contract, not any specific provider's API — is part of the Core Commitment. It will always be Apache 2.0 and provider-agnostic.
Quickstart (current pre-alpha — hermetic, no provider needed)
cd reference/llm-bridge
python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ../validator # bridge depends on validator
pip install -e ".[dev]"
pytest
Use it in code with the bundled EchoProvider (for tests / hermetic CI):
import json
from urml_llm_bridge import Bridge, EchoProvider
red_mug_program = { # the URML the LLM is expected to emit
"profile": "home",
"behavior": {"type": "sequence", "steps": [...]},
}
provider = EchoProvider(scripted=[json.dumps(red_mug_program)])
bridge = Bridge(provider=provider, manifest=manifest, envelope=envelope, profiles=("home",))
result = bridge.translate("Bring me the red mug from the kitchen.")
if result.accepted:
runtime.execute(result.program)
The revision loop runs automatically when the validator rejects the LLM's emission: the bridge feeds the structured errors back to the LLM and asks for a corrected version, up to max_revisions times (default 3).
Using a real provider
Install the extra for the provider you want — the bridge package itself has no SDK dependencies:
pip install urml-llm-bridge[anthropic] # adds the `anthropic` SDK
pip install urml-llm-bridge[openai] # adds the `openai` SDK
Then:
from urml_llm_bridge import Bridge
from urml_llm_bridge.providers.anthropic import AnthropicProvider
provider = AnthropicProvider(model="claude-sonnet-4-6") # reads ANTHROPIC_API_KEY env var
bridge = Bridge(provider=provider, manifest=manifest, envelope=envelope, profiles=("home",))
result = bridge.translate("Bring me the red mug from the kitchen.")
Or OpenAI:
from urml_llm_bridge.providers.openai import OpenAIProvider
provider = OpenAIProvider(model="gpt-4o") # reads OPENAI_API_KEY env var
Both adapters surface their native structured-output mechanism — Anthropic via tool use (with the URML schema as the emit_urml tool's input_schema), OpenAI via response_format={"type": "json_object"} with the schema conveyed in the system prompt. Either way, conformance to the schema is validated downstream by urml_validator.validate() as part of the bridge's revision loop.
What's not in this pre-alpha (lands next)
- CLI integration —
urml translatesubcommand on top ofurml-validator's CLI. - Profile-specific few-shot libraries (drone scenarios, industrial scenarios).
- Multilingual few-shot variants (Hebrew, Spanish, Japanese, Mandarin).
- Conversation memory for follow-up requests within a session.
- OpenAI strict JSON-schema mode — needs schema preprocessing to satisfy the strict-mode constraints (every property required, no
oneOf, etc.). The current adapter usesjson_objectmode plus the schema in the system prompt for portability.
Related documents
/spec/layer-4-nl-grammar/— the prompt contract this bridge implements./reference/validator/— the safety boundary this bridge feeds./examples/— the paired natural-language / URML scenarios used as fixtures.CLAUDE.md§What Claude Should Never Do — the provider-neutrality requirement, in writing.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file urml_llm_bridge-0.1.0.tar.gz.
File metadata
- Download URL: urml_llm_bridge-0.1.0.tar.gz
- Upload date:
- Size: 39.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5fef1808ac4a8d37cfdb7f1732473d00e3fbc48343eeac346c44b034d9b88098
|
|
| MD5 |
21e3cc25b6d02a0e5c1d858dfd001761
|
|
| BLAKE2b-256 |
44c2952a85bb256548a9b7a0b900c3276da0ff29299c5dec60f151bdae861915
|
File details
Details for the file urml_llm_bridge-0.1.0-py3-none-any.whl.
File metadata
- Download URL: urml_llm_bridge-0.1.0-py3-none-any.whl
- Upload date:
- Size: 33.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6f094cadbfc5495a8c36c60048efcaad7e5c7a19a043adfa613bc0b2ed04b2a
|
|
| MD5 |
51c1f947202b952c57315ee5ae25bbe9
|
|
| BLAKE2b-256 |
c4bdda5e87b09bc12100f713a698fe2c28f4f73f70c58891c52e4a117aa3c02f
|