Blog
DEV TIPS & TRICKS

Univeros: How AI Agents Revived My Seven-Year-Old PHP Framework Project

Updated:
Jun 18, 2026
Jun 18, 2026
6 min read
Univeros logo and headline
By
Antonio Ramirez Cobos
,
Co-founder & CTO at 2am.tech
On reviving Univeros, and why layering AI on top of a framework is the wrong approach.

There’s a project folder I’ve avoided revisiting for almost a decade.

About seven years ago, I started working on a PHP framework that quickly became more than just a side project. It included a dependency injection container I was oddly proud of, a middleware pipeline, typed collections, and several unfinished packages with names I eventually couldn’t justify anymore. I poured countless nights and weekends into it, driven by both passion and curiosity.

But then life happened. Clients demanded my focus, I moved to new places, and the next opportunity came along. Slowly, the project fell silent. The folder where all my work lived grew quiet and untouched for years. It became a sort of a small, specific kind of guilt. A reminder of what I once started but never quite finished. 

It's now clear to me that the tedious, repetitive tasks (aka the “plumbing”) killed the joy and momentum of the project, not the challenging parts, which I actually enjoyed. The endless cycle of writing actions, DTOs, responders, routes, migrations, repositories, tests, and updating docs was necessary but extremely unexciting.

But last year's eureka moment was powerful. The very busywork that made me abandon the project is exactly what AI agents excel at today. But there's a catch. The framework has to be built in a way that allows me to actually trust what the agent is doing.

So, I decided to revive the project as Univeros, an agent-native PHP 8.3+ framework. This is the story behind its creation and why it exists now. I hope you’ll find it exciting as I do. 

Three Honest Reasons Behind My Decision

The first one is a bit petty, but I’ll admit it: I wanted all the hours I spent to mean something. There’s a unique sting in seeing your work abandoned. You know the effort was genuine, even if no one ever saw the results. Reviving Univeros was my way of refusing to let seven years of ideas and effort gather dust in a forgotten directory.

The second reason is the real driving force. It’s a deep disagreement.

Just look at how most frameworks are adding AI today: a chatbot on the docs, a “copilot” plugin that autocompletes your code. This AI sits on top, and actually guesses by reading your source files. That is the core problem. An AI agent working in a conventional framework will waste most of its context just trying to figure out basics like “what classes exist here?” or “did this code generation actually work?” It’s slow, expensive, and worst of all, non-deterministic. Run the same prompt twice, and you get two slightly different scaffold results. That noise ruins your diffs and messes up continuous integration (CI), which can’t tell a real change from a coin flip.

I strongly believe this approach is backwards. The framework shouldn’t be something the AI reads and guesses about. It should be something the AI operates directly, deterministically, reversibly, with clear records after every action showing exactly what happened. You can’t just add this on later; you have to design it from the ground up, starting with how requests are handled.

The third reason: I simply missed PHP. More on that later.

What “Agent-Native” Actually Means

Univeros is built around a simple yet powerful idea, driven by specs. Instead of writing complex code for each part of an application, you create just one YAML file that describes an endpoint. With a single command, Univeros then generates the entire vertical slice of the application:

# api/users/create.yaml
operationId: createUser
method: POST
path: /users
summary: Register a new user

input:
  email:    { type: string, format: email, required: true }
  password: { type: string, minLength: 12, required: true }

persistence:
  entity: User
  table: users

idempotency: true

responses:
  "201": { $ref: User }

Run bin/altair spec:scaffold api/users/create.yaml and you get nine files: the Action, the Input DTO, the Responder, the domain stub, the entity, the repository, the migration, the PHPUnit test, the OpenAPI fragment, and the route entry. Ask for a typed TypeScript or Python client, and you’ll get it too. Yes, this means zero manual edits to wire it all together. The only code you write is the business logic inside the domain's __invoke().

Now the “plumbing” that made me abandon the original project is fully automated. But it’s not just about automation. The point is the properties that make it trustworthy for an agent:

Deterministic. Every time you put in the same specs, you get the same output; without variations and without surprises. Consistent, byte-for-byte results no matter the machine or PHP minor version. This consistency means any changes are easy to spot, which makes continuous integration smoother and more reliable. The system isn’t guessing among many possible outcomes; it’s delivering the one true scaffold every time.

Reversible. Every scaffold is recorded in a rewind/replay journal. A bad generation is a journal:rewind away from never having happened. Agents iterate fast and sometimes they can iterate in a wrong way. But these failed attempts are recoverable and reversible. 

Idempotent and webhook-ready by default. Stripe-style Idempotency-Key middleware and signed inbound/outbound webhooks (HMAC, Ed25519, timestamp windows, event-id dedupe, retry, dead-letter) are first-class primitives, driven by the same spec and round-tripping cleanly through OpenAPI 3.1. Instead of distributed-systems plumbing everyone gets wrong, there is a line in a YAML file.

Agent-operable. This one deserves its own section.

Toolbelt I Wish I Had from the Start

Instead of reading the source to understand the framework, an agent working in Univeros reads manifests. The AgentSpec package compiles everything into a deterministic Markdown packet under .agent/. Thus, "what does univeros/http expose?" costs one file read instead of a hundred tokens of spelunking.

When the agent needs to act rather than know, there's a first-party MCP server exposing the framework as 42 callable tools over stdio or HTTP. And every generated project ships an Altair agent skill at .claude/skills/altair/SKILL.md, teaching shell-capable agents like Claude Code to drive the project through bin/altair directly instead of dragging every tool schema into context.

From there it's a real toolbelt, and every command emits structured JSON, so the agent never parses prose to learn what happened:

  • Introspection: a read-only X-ray of a booted app. Bindings, routes, listeners, middleware, specs.
  • Doctor: a health-check runner with CS, PHPStan, and test gates, plus container and DB probes.
  • Suggest: a refactor adviser that flags dead bindings, fat constructors, and routes without specs.
  • Symbol index: find-usages, callers-of, and refactor-impact answers in milliseconds, from the AST plus the specs.
  • Eval: the agent's "let me check" primitive. Run a PHP snippet in a sandboxed subprocess to get a structured result.
  • Events: an append-only .altair/events.jsonl mutation log, making "what just changed?" survive across sessions.
  • Test Reporter and Examples: an AI-native PHPUnit report that maps failures to source, and a test-linked library of canonical patterns so agents copy the idiomatic way instead of inventing one.

Additionally, I wrote a benchmark for the thesis: "Tokens to Ship". It measures how cheaply an agent goes from a cold prompt to a passing acceptance suite, comparing Univeros and a conventional baseline. I published the methodology with its weaknesses listed first, because a benchmark that doesn't survive scrutiny is worse than no benchmark. The claim is deliberately narrow: deterministic, scannable output costs fewer tokens than re-reading the source every time. That's the foundation of the approach.

Coming Home to PHP

I imagined that the sense of nostalgia would be a bittersweet one, much like reading a journal entry from when you were in your twenties.

But this wasn’t the case since PHP has grown up in the meantime.

There’s almost nothing left of the language I knew before 8.3; it has evolved significantly since then. There are now real typed properties: readonly classes, enums, constructor promotion. First-class attributes now turn the “magic” used by the framework into something the engine itself understands. An agent can read this with reflection instead of guessing at. It’s clear that the ecosystem has become a “grown up.”

The Univeros framework was always intended to be free of magic and fully typed. I just didn't have a language mature enough to make it pleasant, or a reason compelling enough to finish. Now I have both. 

What's in the Box

Univeros consists of 40 independently usable packages under one bundle. Install everything with composer require univeros/framework, or pick pieces: univeros/cache, univeros/http, univeros/container. It follows PSR-7/15/14/6/16 standards where applicable. The HTTP stack is a PSR-15 middleware pipeline with an Action / Domain / Input / Responder lifecycle, FastRoute, and JWT/basic/digest auth. Persistence is a thin Repository / UnitOfWork contract over Cycle ORM v2. Messaging bridges Symfony Messenger with attribute-driven handler discovery. There's a runtime auto-wiring DI container, a PSR-14 event dispatcher, a command bus, sixteen input filters, eighteen validators, typed data structures in pure PHP, caching across four backends, as well as cryptographic primitives done carefully.

It's fully modular by design, too. A pluggable module registers one line in config/modules.php and self-wires its routes, entities, and migrations into the host. The core is named Altair.

Give It a Try

If you've ever watched an agent waste half its context window just to figure out whether its last edit worked, do the following:

composer create-project univeros/univeros my-api

A single command gives you a complete, running, tested API: a working /ping, a passing test, and the whole spec-driven toolchain wired. From there, write a spec and ship your first real endpoint in minutes.

Seven years is a long time to leave something in a drawer. But I couldn’t have built the version I actually wanted until now. It was imagined as the thing that would eventually sit next to me and handle the plumbing.

That thing finally arrived. So I finished the framework for it. 

In the second part of this blog series, I’ll cover the features and capabilities of Polaris, Univeros’ official identity module that provides a complete authentication and authorization system for applications built on the framework.

Univeros is an MIT licensed project, built at 2am.tech

Build Agent-Ready Backend Systems with 2am.tech

We design and engineer specification-driven architectures that make development supported by AI deterministic, testable, and safe for deployment. Let’s talk.

Experience Seamless Digital Transformation

Overwhelmed by implementing process automation? Partner with 2am.tech for end-to-end support in reaching your company's full potential, from planning and development to training and maintenance.

Learn More

Don't miss out on
our latest insights
– Subscribe Now!

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Share This Post
Back to Blog
Don't miss out on
our latest insights
– Subscribe Now!
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Navigate
Start Now