Skip to content
← Blog
  • product
  • engineering

Why we built the action layer

Every Work OS gets asked the AI question eventually. Most answers are a chatbot bolted on. Ours is an architectural primitive.

By Odexy team

When we started Odexy in 2025, we had two beliefs that locked the architecture:

1. AI was going to operate software, not just summarize it. Every "AI assistant" product launching that year was a chat bubble that drafted text — the human still had to do the work. The agent-operates-the-product world was coming faster than the demo videos suggested.

2. The way every existing system was bolting AI on was a mistake. Every CRM, every project tool, every HR system: build the product, ship it, then six months later add a chatbot that "knows your data." Two backlogs. Two authorization models. Two audit logs. Permission drift on day one.

So we made the action layer the first thing. The product's primitive isn't the database table. It's the action.

What is an action

An action is one Zod schema (the input), one handler function (the logic), one policy (who can call it), one description (what it does to a reader). That's it. Every user-performable operation in Odexy is an action. The UI calls it. The AI calls the same one. The MCP server exposes the same one. The CLI calls the same one.

When we ship recruitment.offer.send, we don't ship a UI flow and then later add an AI tool that wraps it. There is no wrapper. The UI button and the AI tool call the same handler.

What this gives you

1. Same-day AI parity. A new feature is AI-callable the day it ships. There's no second backlog of "AI-enable this feature."

2. No permission drift. The policy that gates the UI button gates the AI call. If your role loses access to compensation data tomorrow, your AI loses it automatically.

3. One audit log. Every action, regardless of caller, writes the same audit_log row. Same columns, same retention, same query interface.

4. Deterministic replay. The action's input hash and output hash are recorded. Run the same input again, get the same output. Show an auditor.

What we gave up

This architecture asks a lot of every feature. You can't ship a half-built action. You can't have UI logic in a React component (it belongs in the action). You can't add validation "later" (the schema is the source of truth). You can't grandfather an old endpoint that doesn't fit (we did, briefly, and regretted it).

The product moves slower per-feature than it would if we let UI logic sprawl. We chose that trade because we believed the AI was going to be a first-class operator, and we wanted the architecture to be ready when it arrived. By mid-2026, every shipped action is AI-callable. Every action is in the audit log. There is no parallel chatbot.

What's next

The action layer is the thing we'd write again. The two surprises we still navigate:

  • Action ergonomics. Every new feature wants to be three actions, not one. The temptation to write convenience wrappers is constant. We resist it; the registry stays atomic.
  • Frontend discipline. React components want to do too much. We push everything to actions; the components render. It's a discipline, not a framework.

If you're building a Work OS — or any product where AI is going to be a real operator — start with the action layer. The chatbot is the wrong shape.

— The Odexy team

Subscribe to the Odexy changelog.

One email every ~2 weeks. Honest product notes, no marketing pitches.

We email you only when there's something honest to say. Unsubscribe in one click.