Core Concepts

VibeBlocks is built on a few core abstractions that separate business logic from orchestration.

1. ExecutionContext

The ExecutionContext[T] is the “single source of truth” for your flow. It is a generic container that holds:

  • Data (T): Your custom dataclass, Pydantic model or dictionary (e.g., UserData).

  • Trace: A chronological log of Events (start, end, error, retry).

  • Metadata: Arbitrary key-value pairs (e.g., execution ID, timestamps).

  • Completed Steps: A set (completed_steps) used internally for safely tracking executed steps during robust compensations.

The context is passed to every block, allowing them to read and modify state in-place. It is designed to be fully serializable to JSON for debugging and persistence. When deserializing via from_json, VibeBlocks automatically attempts to reconstruct strict types such as dataclasses or Pydantic models if you provide the class parameter.

2. Executable Units

VibeBlocks uses a composite pattern where everything is an Executable:

Block (Leaf)

The smallest unit of work. It wraps a Python function (sync or async) and adds:

  • Retry Policy: Configurable retries with backoff and jitter.

    • max_attempts (int): Total attempts before failure (default: 1).

    • delay (float): Base wait time in seconds (default: 1.0).

    • backoff (BackoffStrategy): Wait strategy (FIXED, LINEAR, EXPONENTIAL).

    • retry_on (List[Exception]): Exceptions that trigger a retry.

    • give_up_on (List[Exception]): Exceptions that immediately fail.

  • Compensation: Logic to undo changes if the flow fails later.

Chain (Composite)

A linear sequence of blocks or sub-chains. It executes steps in order. If a step fails, the chain fails and bubbles the error up.

Flow (Orchestrator)

The top-level container that defines the Failure Strategy:

  • ABORT: Stop immediately on error.

  • CONTINUE: Log error and proceed (best-effort).

  • COMPENSATE: Stop and run undo logic for all successful steps in reverse order (LIFO).

3. Runners

Runners handle the execution loop and are strict about async runtime evaluation:

  • SyncRunner: Executes flows synchronously. Raises a RuntimeError if it encounters an async block or an async compensation function that escaped static detection.

  • AsyncRunner: Executes flows asynchronously. Can handle both sync and async blocks transparently.

Warning: VibeBlocks relies on static inspection (inspect.iscoroutinefunction) to build the execution tree. Always declare asynchronous user functions properly with async def. If a standard def function manually returns an awaitable (like returning asyncio.sleep()), the static parser will flag it as synchronous, potentially causing a RuntimeError at execution time in SyncRunner.

4. Zero-Gravity Philosophy

VibeBlocks intentionally avoids heavy dependencies. It does not include:

  • Database drivers

  • HTTP clients

  • Task queues (Celery/Redis)

It provides the structure; you provide the infrastructure. Services (like DB connections) should be injected into your blocks (for example via closures or class-based callables) rather than carried in the serialized context.