AI execution kernel · open source · BSD-3-Clause
The AI execution kernel for deterministic, policy‑gated workflows.
Praxec composes pluggable capabilities — MCP tools, CLIs, services, scripts, and native modules — while constraining LLMs to bounded execution contexts.
workflows:
release:
initialState: review
states:
review:
transitions:
run_checks:
target: verified
executor: { kind: cli, command: just ci } # a CLI is a capability
verified:
transitions:
approve:
actor: human # so is a person
target: approved
approved:
transitions:
publish:
target: live
executor: { kind: rest, connection: deploys } # so is a servicethe inversion
The workflow chooses. The kernel enforces.
Most agent systems hand the model a list of tools and a prompt full of rules, then hope. Praxec turns that inside out: the workflow declares which capabilities each step may use, the kernel grants bounded access, and every result is validated before the state moves.
| Most agent systems | Praxec |
|---|---|
| LLM chooses tools | Workflow chooses capabilities |
| Prompt governs behavior | Kernel enforces transitions |
| Tool list grows with complexity | Capability surface stays controlled |
| Agent is the orchestrator | Workflow engine is primary |
| Best-effort guardrails | Validated state transitions |
A rule that lives in prose is a rule the model can talk itself out of. A rule that lives in the kernel isn't up for debate.Read the full mechanism →
the execution loop
Four steps, every time
Every unit of work runs the same cycle. It's the same loop whether the capability is a shell command, an HTTP call, a human approval, or an LLM turn.
Workflow selects
The current state declares which transitions exist and which capability each one uses. Nothing else is on the menu.
declared in yamlKernel grants
Guards, actor rules, and input schemas run first. Access is scoped to this one step — not a standing permission.
bounded accessCapability executes
A CLI, a service, a script, a person, or a model does the work — with timeouts, retries, and fallbacks declared alongside it.
any executor kindKernel validates
Output is checked against the declared schema before the state transition commits. Bad results don't advance the workflow.
then, and only then, transition
the capability model
Anything that does work is a capability
A capability is a typed unit of work. Behind it sits one of eleven executor kinds — MCP is one transport among many, not the whole story:
- cli
- script
- rest
- mcp
- human
- llm
- agent
- workflow
- parallel
- pipeline
- noop
Two tools, no matter what
The model sees exactly two tools — praxec.query to read and discover, praxec.command to act. Everything routes through them. Wire in one capability or five hundred; the tool list never grows.
Links, not lists
Every response hands back the legal next moves as links, with arguments prefilled. The model navigates the workflow the way a browser navigates the web — it never needs a catalog of everything.
LLMs stay inside the boundary
When a step is LLM-driven, the transitions legal at that stateare the model's tool list — with per-turn caps on iterations, time, tokens, and cost. Injecting extra tools isn't a config option.
on the wire
What a refused move actually looks like
The agent is in review. Checks haven't run. It reaches forpublish anyway — and finds the move isn't there:
→ praxec.command { "transition": "publish" } # tries to skip ahead
← { "result": { "status": "rejected" },
"error": { "code": "INVALID_TRANSITION" },
"links": [ { "rel": "run_checks" } ] } # the legal move, handed backNot discouraged — unreachable. And the refusal hands back the one legal move, so the agent recovers on its own: run the checks, and only then does publish appear. Every attempt, including this refused one, lands in the audit log.
built for production
The boring parts are the point
Deterministic execution needs unglamorous machinery. It's all here.
praxec check
Static config validation that fails CI on unreachable states, dead ends, and schema errors — before anything runs.
px doctor
Preflight for the runtime: provider keys, model bindings, and script references verified before a workflow walks.
Durable stores
Memory, file, or SQLite — including multi-process SQLite on one host with optimistic locking. No external services.
Audit & replay
Every action emits a structured JSON event — including the refused ones. Route to file, stdout, or your observability stack.
Hot reload
Send SIGHUP and the kernel validates the new config first, then swaps. In-flight workflows continue uninterrupted.
Navigable state
Discovery is HATEOAS all the way down — query any workflow and get its live state plus the legal moves from here.
get started
Running in two commands
$ curl -fsSL https://raw.githubusercontent.com/praxec/praxec/main/install.sh | bash
$ praxec init --with-starter-packs --yes # scaffold config, wire packs + editor, verify readinesspraxec is the kernel — an MCP server you wire into Claude Code, Cursor, or any agent host. init --with-starter-packs --yesscaffolds a working gateway.yaml and models.yaml, wires the starter packs and your editor's MCP config, and finishes with a doctor readiness check — restart your editor andpraxec.query / praxec.command appear.
Want the mechanism first, or a different editor/pack setup?See the fast path and every flag →