Ormaos · Runtime context for Python

Ormaos

10 min read Original article ↗

Runtime context for Python

What happened inside your Python execution?

Ormaos records and shows it. The runtime context for your agent and for you. Built for your coding agent to query from the terminal. Plain enough for you to read too.

Not released yet · Coming November 2026

You’ll get a personal email from me asking what you think, and a note for every release and new feature. Reply “stop” and you’re off the list. How I handle your email.

Python 3.12+ · Open source, Apache 2.0 · Self-hostable · CLI only, no dashboard (yet)

Your agent sees the code and the result. Not what happened in between.

The code shows what could happen. The test output shows how it ended. What happened in between was never written down, unless you logged that exact thing.

The code shows every path, not the one taken

Which branch ran, which function returned early, how many times a loop went around: none of it is in the source.

A swallowed exception doesn’t show up

When an exception is caught and ignored, there’s no traceback and no error message. All that’s left is whatever the code did next.

Every new question costs another run

Without a recording, checking something new means adding a print or a breakpoint and running again. With one, you ask the recording before you run again.

Ormaos records what ran, so your agent can read it instead of inferring it.

One bug. Find where, then look deep.

A test fails because a function returns an empty list. No exception, no error message, and the code looks fine.

Step 1 · Record the whole run at level 2. Find where to look.

$ ormaos run -l 2 -- pytest tests/test_pipeline.py::test_import
FAILED tests/test_pipeline.py::test_import - assert 0 == 1
ormaos: recorded r_7f3a2 · level 2 · exit code 1 · next: ormaos show

$ ormaos exceptions --swallowed

e1  ValueError: time data '2025-12-31' does not match format '%d/%m/%Y'
    raised     dates.py:22      in parse_date    (c41)
    swallowed  pipeline.py:56   in normalize     (c40)  except ValueError

    1 swallowed · recording r_7f3a2 · level 2 · whole process
    next: ormaos tree --at c40
          or record deeper: ormaos run -l 3 -s normalize -- <same command>

Step 2 · Record at level 3, only there.

$ ormaos run -l 3 -s normalize -- pytest tests/test_pipeline.py::test_import
FAILED tests/test_pipeline.py::test_import - assert 0 == 1
ormaos: recorded r_9c1e4 · level 3 · scope: normalize · exit code 1

$ ormaos path --function normalize --not-run

normalize · pipeline.py · call c40 · recording r_9c1e4
51  ▸ records = []
52  ▸ for row in rows:                    1 iteration
53  ▸     date = None
54  ▸     try:
55  ▸         date = parse_date(row)      raised ValueError (e1)
56  ▸     except ValueError:
57  ▸         pass
58  ▸     if date is None:                True
59  ▸         return []                   returned list (empty)
60        records.append(date)            never ran
61    return records                      never ran

level 3 · scope: normalize · next: ormaos tree --at c40

The exception was swallowed, the function took the early return, and the list came back empty. Your agent reads what happened instead of inferring it.

Design preview · The real output may change before release

As deep as the question needs

Start wide and cheap. Go deep only where it matters. Level 3 always needs a scope: one or more functions, or a module.

Levels 1, 2 and 3
Level 1 The basics Level 2 The call tree Default Level 3 The path
Records Duration and CPU. Database and HTTP calls with the line that made them. The raised exception. Python and package versions, and your git commit. Level 1, plus: every call in your code. Every exception, including swallowed ones. The shape of arguments and returns, never the values. Calls into libraries, by name and duration. Level 2, plus: every line that ran, each branch taken, loop iterations, the lines that never ran, and the shape of local variables.
Where The whole process The whole process Level 2 on the whole process. Line detail only inside the functions or module you choose. Scope required.
Use it when You want a cheap record of any run. Something failed and you don’t know where. You know where, and need to see why.
Cost Lowest. Only the run itself and its database and HTTP calls. Moderate. One event per call in your code. Library internals are skipped. Highest. Level 2 cost, plus one event per line inside the scope.
Navigate with show · show --full Available at every level. + tree · exceptions Who called whom. What went wrong, swallowed or not. + path The lines a function ran, inside the scope.

ormaos show

The summary of the run, on one screen: outcome, where the time went, exceptions and swallowed ones, what wasn’t collected, and the next command to run.

ormaos show --full

Everything that was recorded, with nothing cut. It warns you about the size first. For when navigating isn’t enough.

Why level 2, not 3?

Level 2 finds where. Level 3 explains why, only there. Each level includes everything below it, but recording every line of a whole process would be slow and huge, so level 3 makes you pick the spot.

What about real numbers?

Overhead per level is measured and published before release. It never changes your program’s state, but it does change timing, noticeably at level 3. Timing-sensitive bugs can behave differently while recorded.

Built on sys.monitoring (PEP 669).

They detect. Ormaos investigates.

It doesn’t replace anything you use. You keep both.

Your observability · Always on

Tells you that something went wrong

An error, a slow span, an alert. Across every request, all the time.

Sentry, Datadog, Logfire.

Ormaos · On when you need it

Shows what happened inside

For one execution: the calls, the swallowed exceptions, the path through the code you scope. As deep as you ask.

What ships in November

Everything Ormaos does can be done with a command: recording, reading, checking status, running the server. If you can type it, your agent can run it. No dashboard (yet).

  • ormaos run -- <cmd>

    Record any Python command, including pytest and Django management commands.

  • with ormaos.record():

    Record a block from inside your code.

  • list · show · tree · exceptions · path · status

    Your agent reads --json. You read the same answer as text. Every answer ends with the next question to ask.

  • ormaos guide

    Short instructions written for your agent: when to record, which level, what to ask first.

  • ormaos local start

    Works on your machine with no account. The same server is self-hostable for your team.

  • Levels 1, 2, 3

    Threads, asyncio and child processes. Database and HTTP calls from the Django ORM, requests and httpx. Python 3.12+. Linux first; macOS planned.

Later, not in the first release: recorded values (redacted by default) and where each came from · diff between a passing and a failing run · arming a recording in production · integrations with the tools you already use.

What Ormaos is making

Ormaos is open source software that records what happened inside a Python execution, so your coding agent can read it from the terminal. It starts from one problem: your agent can read the code, but not what happened when it ran. You choose how deep to record, from every call and every exception, including the swallowed ones, down to each line that ran in the functions you scope. It doesn’t replace the tools you already use: they tell you something went wrong, and Ormaos shows what happened inside. The recorder, the CLI, the server and the recording format are Apache 2.0. A hosted server, in beta by request, is how Ormaos plans to make money. The first release ships in November 2026.

Where it’s going. Two directions. Deeper, as far as the interpreter allows. And lighter, until it’s cheap enough to leave on. Even then, it records; it doesn’t alert. After that, more languages than Python, and an open format for execution recordings that any tool can write and read.

Open source. Apache 2.0.

The recorder, the CLI, the server and the recording format are all open source under Apache 2.0. Read it, run it, self-host it, build on it.

ormaos-python

The recorder. Standard library only, no third-party dependencies.

ormaos-cli

The terminal interface. Standard library only.

ormaos-server

Analysis and storage. Runs locally, on your server, or hosted (beta, by request).

ormaos-format

The recording format, as a written spec.

The repositories open on release day at github.com/ormaos

Straight answers

Something new to add to your stack. Not something to swap out.

What Ormaos is

  • Something new to add, not a replacement. Keep Sentry, Datadog or Logfire: they watch every request, all the time. Ormaos records one execution in depth, down to swallowed exceptions and the lines that ran.
  • A recording you start when you need one. ormaos run -- <cmd> or a with ormaos.record(): block. Nothing is recorded until you ask.
  • As deep as you choose. Every call and every exception by default, swallowed ones included. Every line that ran, inside the functions you scope.
  • Built for your coding agent to read. Terminal commands with --json, and every answer points to the next question. You read the same output as text.
  • Yours to run. Open source under Apache 2.0. On your machine with no account, on your own server, or hosted (beta, by request).

What Ormaos is not

  • Not a replay debugger. It records and lets you query what ran. It doesn’t re-execute your program.
  • Not an APM. No alerts, no always-on monitoring. It sits next to yours.
  • Not a profiler. It records durations, but it’s built to show what ran, not to tune hot paths.
  • Not LLM observability. It doesn’t watch your LLM and never looks at prompts or model responses. Your coding agent reads what Ormaos records.
  • Not for every Python. 3.12 and newer only, because that’s where sys.monitoring lives. Linux first, macOS planned, no Windows yet.

What gets recorded, and what never does

As designed for the first release

  • Shape, not values. Levels 1 to 3 record type, size, empty or not.
  • Exception messages are redacted before being written: anything that looks like an email, token, key, password, long number or a URL with credentials.
  • Never recorded: SQL query parameters, request bodies, response bodies.
  • You choose where it lives. Recordings stay on your machine unless you point them to your own server or the hosted beta.

Open source · Apache 2.0 · Built in public

I’d rather hear the objection now than in November.

Any feedback helps: whether the problem is real for you, what’s unclear on the page, any questions, or why you think it wouldn’t work. And if something like this already exists for Python, please tell me.

You’ll get a personal email from me asking what you think, and a note for every release and new feature. I answer every reply myself. Reply “stop” and you’re off the list. How I handle your email.