For teams letting AI agents touch production.
Your agent just sent that email twice.
Praxis would have stopped it. Praxis is the one path every action your agents take to the outside world — Slack, SMTP, GitHub, your own APIs. Preview before running. Block what your policy disallows. Never fire the same call twice. Replay exactly what happened later.
Stop double-sendsSame email, same Slack, same Jira ticket — Praxis collapses retries before they fire.
Dry-run anythingPreview your agent's next 10 actions before you let it run them.
One audit, one query"Show me every action this agent took last quarter" — answered from one log, not five vendor dashboards.
Scenario
Discover, dry-run, execute, replay, idempotent retry.
No SMTP/Slack credentials required — degraded handlers return a
simulated success so the loop completes on a laptop. The
load-bearing demo: every step persists to the audit log, and
praxis log show reconstructs the entire lifecycle
from those rows alone.
$ make build
$ ./bin/praxis caps list
NAME IDEMPOTENT SIMULATABLE
send_email true true
send_message true true
http_request true true
github_create_issue ...
$ ./bin/praxis run send_email \
'{"to":"alex@example.com","subject":"hi","body":"hello"}' --dry-run
{ "action_id": "act_7a1", "status": "simulated",
"preview": { "to": "alex@…", "subject": "hi", "body_chars": 5 } }
$ ./bin/praxis run send_email \
'{"to":"alex@example.com","subject":"hi","body":"hello"}'
{ "action_id": "act_7b2", "status": "succeeded", "external_id": "" }
$ ./bin/praxis log show act_7b2
received -> validated -> policy.allow -> executed -> succeeded
inputs: to=alex@example.com subject=hi
policy: rule=default decision=allow
duration: 12ms
$ ./bin/praxis run send_email \
'{"to":"alex@example.com","subject":"hi","body":"hello"}' \
--idempotency-key act_7b2
{ "action_id": "act_7b2", "status": "succeeded", "from_cache": true }
# second call short-circuits — no double effects, recorded in audit
How it differs
Where Praxis fits.
Praxis is not a workflow engine, not an agent framework, not a tool router. It's the layer where the act of doing one thing is governed, simulated, and reconstructible.
Architecture
Caller → Executor → vendor + audit + outbox.
One executor. One audit chain. One outbox to Mnemos. CLI / HTTP / MCP all run the same path; the audit can't diverge because there's only one path to diverge from.
Nous · agent · CLI · MCP
all hit the same executor
validate → policy → idempotency → run
capability registry · JSON Schema · DryRun parity
vendor
slack · smtp · github · http_request
replay-from-audit
received → … → terminal · Mnemos outcome
ListCapabilities · Execute · DryRun — the public surface never expands
StorageSQLite (default) · Postgres · in-memory · OpenTelemetry traces
Pluginssigned Go plugins — add new actions without rebuilding the binary
Run it
Build. Discover. Dry-run. Execute. Replay.
git clone https://github.com/felixgeelhaar/praxis.git
cd praxis && make build
./bin/praxis caps list
./bin/praxis run send_email '{"to":"a@example.com","subject":"hi","body":"hello"}' --dry-run
./bin/praxis run send_email '{"to":"a@example.com","subject":"hi","body":"hello"}'
./bin/praxis log show <action-id>
HTTP surface (same executor):
./bin/praxis serve --port 8080 &
curl -H 'Authorization: Bearer …' \
-d @action.json \
localhost:8080/v1/actions
./demo.sh — the CLI
flow above is the demo. DryRun parity isn't 100%
across every handler; multi-tenant policy + reversibility are
scaffolded, not the headline.
Cognitive stack context
Praxis works alone. Plugs into a four-system stack.
Mnemos remembers, Chronos watches time, Nous decides, Praxis executes. Olymp drives the loop. Each is independently usable.
Mnemos · memory
Evidence-linked claims with point-in-time replay and contradiction detection.
Chronos · time
Pattern detection over time-series data. Typed signals, not threshold alerts.
Nous · decisions
Commitment extraction, risk evaluation, intervention generation.
Olymp · runtime
Drives observe → understand → decide → act → learn end-to-end.