ESC

Type to search...

What is IOP?

Intent-Oriented Programming (IOP) is a paradigm where data declares what it needs, and the runtime handles how.

It’s not anti-OOP. It’s not anti-FP. It’s a third way that combines the best of both: data carries intent (like objects carry state), and processors are pure functions (like FP transforms).

The Problem

Every time you write an endpoint, you make the same infrastructure decisions:

def save_user(user):
    # 1. Which database? MySQL? PostgreSQL? MongoDB?
    db.insert("users", user)

    # 2. How to cache? Redis? In-memory?
    cache.set(f"user:{user.id}", user, ttl=300)

    # 3. Should I encrypt? Audit? Log?
    encrypt(user.email)
    audit_log("user_created", user)

    # 4. What if it fails? Rollback cache? Retry?
    try:
        db.commit()
    except Exception as e:
        cache.delete(f"user:{user.id}")
        raise

These decisions repeat across every function in every project. The infrastructure logic mixes with business logic. Changing the database means rewriting every function.

The IOP Solution

What if your data could tell the system what it needs?

from evoid import Intent, Level

# Declare WHAT you want — the runtime decides HOW
GET_USER = Intent(
    name="get_user",
    level=Level.STANDARD,  # Normal business data
    metadata={"method": "GET", "path": "/users/{id}"},
)

# Your handler focuses on business logic only
async def handle_get_user(ctx) -> dict:
    user_id = ctx.intent.metadata.get("user_id")
    # No database choice here — the pipeline handles it
    # No caching logic here — the pipeline handles it
    # No encryption here — the pipeline handles it
    return {"id": user_id, "name": "Alice"}

That’s IOP. You declare what you want (the Intent), and the runtime handles how (the pipeline).

How It Works

Your Intent (what you want)

Intent Resolver (reads Intent level + metadata)

Pipeline Composer (builds execution plan)

Processor 1: validate    → checks input
Processor 2: authorize   → checks permissions (evoid-auth plugin)
Processor 3: your handler → business logic
Processor 4: audit       → logs the action (evoid-auth plugin)

Result (success/failure with timing)

Each processor is a pure function that receives a Context and returns a result. The pipeline composes them. You don’t call them directly, the runtime does.

Three Intent Levels

Each level maps to a different pipeline with different infrastructure behaviors:

LevelWhat It MeansPipelineTimeoutUse Case
EPHEMERAL”I don’t care if this disappears”validate5sSessions, cache, temp data
STANDARD”Normal business data”validate, authorize10sUser profiles, posts, comments
CRITICAL”This must never be lost”validate, authorize, audit, protect30sPayments, medical, legal

You choose the level. The runtime chooses the infrastructure.

# STANDARD: Showing your ID at reception
GET_PROFILE = Intent(name="get_profile", level=Level.STANDARD)
# Pipeline: validate → authorize → handler (10s)
# "Who are you?" "Can you do this?" "Okay, here you go."
# Balanced. Most business operations live here.

# CRITICAL: Wire transferring a million dollars
PROCESS_PAYMENT = Intent(name="process_payment", level=Level.CRITICAL)
# Pipeline: validate → authorize → audit → protect → handler (30s)
# Papers signed, cameras rolling, guards standing by.
# Every step logged. Every action traceable. Forever.
```

Traditional vs IOP

# Every function repeats infrastructure decisions
async def get_user(user_id: int):
    user = await db.get_user(user_id)      # Which db?
    cached = cache.get(f"user:{user_id}")   # Which cache?
    if cached:
        return cached
    encrypted = encrypt(user.email)          # Which encryption?
    audit_log("user_accessed", user)         # Which logger?
    cache.set(f"user:{user_id}", user)       # Which cache?
    return user
# Declare intent — runtime handles infrastructure
GET_USER = Intent(
    name="get_user",
    level=Level.STANDARD,
)

async def handle_get_user(ctx) -> dict:
    user_id = ctx.intent.metadata.get("user_id")
    # Just business logic — no infrastructure decisions
    return {"id": user_id, "name": "Alice"}

# Pipeline: validate → authorize → handle_get_user
# Infrastructure: chosen by level, configurable via plugins

The IOP version doesn’t eliminate infrastructure; it moves it to the pipeline where it’s configured once and applied everywhere.

Key Principles

  1. Intent is Permanent: Once declared, the Intent stays with the data through its entire lifecycle
  2. Infrastructure is Temporary: Swap databases, caches, queues by changing pipeline config, not business logic
  3. Data Carries Intent: Your data models tell the system how to handle them
  4. Pipeline is Composition: Processors are pure functions composed together
  5. Processors are Independent: Each does one thing, knows nothing about others

Why This Matters for AI

IOP was designed for a world where AI agents need to understand and interact with your system:

  • Schema Export: Intents export as JSON Schema, making them machine-readable
  • MCP Integration: Expose Intents as MCP tools for AI agents
  • Self-Describing: An AI agent can read an Intent and understand what it does, what level it needs, and what pipeline it runs
# AI agents can discover and call your intents
GET_USER = Intent(
    name="get_user",
    level=Level.STANDARD,
    metadata={"method": "GET", "path": "/users/{id}"},
    # AI agent sees: "This intent gets a user by ID"
    # AI agent knows: "This is standard level, needs authorization"
)

Learn More