CLI and toolkit to generate /.llm/ layers conformant to ENACTABLE/1.0 from OpenAPI/Swagger
Project description
enactable — CLI for ENACTABLE/1.0
Generate, validate and serve /.llm/ layers conformant to ENACTABLE/1.0 from an existing OpenAPI/Swagger specification.
The principle: a Swagger file describes how to call an API. ENACTABLE describes why an endpoint exists, which human intention triggers it, what effects it has, and how much autonomy to give an agent. This CLI infers the first layer automatically and guides you in completing what an LLM cannot deduce.
Installation
pip install enactable
# optional, for LLM-assisted generation:
pip install "enactable[all]" # anthropic + openai + pyyaml
Requires Python >= 3.9. The only core dependency is pydantic.
The four commands
generate — from OpenAPI to a /.llm/ draft
enactable generate ./swagger.json -o ./.llm --app-id com.acme.app
Reads the OpenAPI spec (2.0 or 3.x, JSON or YAML), infers manifest, actions, forms, permissions and a context skeleton, and writes the files to the output directory.
With ANTHROPIC_API_KEY or OPENAI_API_KEY set in the environment it uses an LLM for richer intents and hints. Without a key, it falls back to a deterministic heuristic generator that infers from patterns (HTTP method, field naming): it always works, even offline.
--llm flag: auto (default), anthropic, openai, heuristic.
validate — check conformance and consistency
enactable validate ./.llm
Two levels of checks: schema conformance and cross-document consistency. It enforces the safety rules of the draft, including:
- an irreversible action must require confirmation
- an irreversible action cannot be
autonomous - permissions cannot reference non-existent actions
- forms cannot reference non-existent actions
- write operations should declare their
side_effects
It exits with a non-zero code if it finds errors, so it can be used in CI.
review — complete the non-inferable fields
enactable review ./.llm
Interactive wizard for what no LLM can deduce from the API: which fields must never be inferred (cannot_infer), the domain business rules, and a review of the proposed autonomy for each action.
serve — expose the layer over HTTP
enactable serve ./.llm -p 3000
Standard-library server (zero dependencies) that mounts:
GET /.llm/→ machine-readable index of the documentsGET /.llm/<doc>.json→ the individual documents, with anX-Enactable-Versionheader and CORS
Typical workflow
enactable generate ./openapi.json -o ./.llm # 1. automatic draft
enactable review ./.llm # 2. complete domain and safety
enactable validate ./.llm # 3. check conformance
enactable serve ./.llm # 4. expose the layer
Architecture
enactable/
├── core/
│ ├── models.py # ENACTABLE schema as Pydantic models
│ ├── validator.py # conformance + cross-document consistency + safety rules
│ └── serializer.py # EnactableSpec <-> /.llm/ files
├── generator/
│ ├── parser.py # OpenAPI 2.0 / 3.x -> internal representation
│ ├── llm.py # LLM provider + deterministic heuristic fallback
│ ├── generator.py # orchestration parser -> LLM -> EnactableSpec
│ └── prompts/ # prompts for actions, forms, permissions
├── cli/
│ ├── main.py # argparse entry point
│ ├── output.py # colored output (ANSI)
│ └── commands/ # command implementations
└── server/
└── server.py # HTTP server for the /.llm/ layer
The key design point: the generator is not required for correctness. It produces a draft; the validator is the authority on conformance. A hand-written spec passes through the same validator. Generator and framework have distinct roles.
What is inferable and what is not
| Inferable from the API (automatic) | Requires human input (review) |
|---|---|
intent, side_effects, reversible |
domain business_rules |
requires_confirmation |
cannot_infer (sensitive fields) |
capabilities, auth.type |
final safety autonomy |
forms with basic hints |
disambiguation on edge cases |
The CLI is honest about this boundary: it generates everything deducible, flags the gaps explicitly, and does not pretend that safety decisions can be automated.
Created by Antonio Stassi · 2026 · Draft 1.0
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 enactable-1.0.0.tar.gz.
File metadata
- Download URL: enactable-1.0.0.tar.gz
- Upload date:
- Size: 21.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
544adc19e0d29d17e11fec72d0f15b19b755f5b3ba1ba888cc1533032410b07b
|
|
| MD5 |
9c688450d4b5514aaf4db465f478a20a
|
|
| BLAKE2b-256 |
cbe104216b1808f89198b9cd287dc15e608d65c886546277ac6abe55a76d7812
|
File details
Details for the file enactable-1.0.0-py3-none-any.whl.
File metadata
- Download URL: enactable-1.0.0-py3-none-any.whl
- Upload date:
- Size: 24.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bffe9f8bb97249145d88cab5e876bd58d039093ddbcd0570d9ed64b5d4705fbb
|
|
| MD5 |
846c517aa707405b71d234bfdf6e4a35
|
|
| BLAKE2b-256 |
7b5cf24f2cf4fd34b7949483fd19c411f6075d5cd0ddc95e20c5f8bb0a76a2a2
|