Skip to content

Execution Runtime

VibeBlocks provides a dual-engine architecture designed to handle both classic synchronous logic and modern asynchronous I/O (essential for AI API calls). This document details how to choose and configure the appropriate runner for your environment.

1. Dual-Runner Architecture

The framework abstracts execution through two primary classes: SyncRunner and AsyncRunner. These engines manage the orchestration lifecycle, including timing, tracing, and error propagation.

SyncRunner

The SyncRunner is optimized for deterministic, CPU-bound tasks or legacy environments where asyncio is not present.

  • Behavior: Executes blocks sequentially within the main thread.
  • Safety Guard: It performs a runtime check on every step. If a block returns a coroutine (indicating an async def function was used), the SyncRunner will raise a RuntimeError rather than allowing the task to fail silently.

AsyncRunner

The AsyncRunner is the recommended choice for modern AI applications. It natively supports mixed workloads.

  • Behavior: Uses a non-blocking event loop.
  • Capability: It can execute both synchronous def functions and asynchronous async def blocks. Synchronous functions are executed directly, while awaitables are awaited.

2. Smart Async Detection

VibeBlocks uses static inspection to build its execution tree. This is critical for maintaining "Zero-Gravity" performance without the overhead of heavy runtime wrappers.

from vibeblocks.utils.inspection import is_async_callable

# VibeBlocks automatically identifies:
# 1. async def functions
# 2. functools.partial wrappers around async functions
# 3. Objects with an async __call__ method

Engineering Note: While the framework is robust, it relies on standard Python definitions. Avoid patterns where a standard def function manually returns an awaitable (e.g., return asyncio.sleep(1)). This "sneaky" async behavior can bypass static detection and cause runtime failures in the SyncRunner.

3. Timeout Management

Reliability requires strict control over execution time. VibeBlocks implements timeouts differently depending on the runtime to ensure resource safety.

Synchronous Timeouts

Synchronous blocks utilize a shared ThreadPoolExecutor (_TASK_TIMEOUT_EXECUTOR) that is reused across all timed blocks in the same process. This avoids the overhead of spawning new threads for each timeout and prevents thread leakage when many blocks run concurrently.

@block(timeout=2.0)
def heavy_computation(ctx):
# If this takes > 2s, a BlockTimeoutError is raised
...

Asynchronous Timeouts

Asynchronous blocks leverage asyncio.wait_for, providing native, low-overhead cancellation of pending tasks without the need for additional threads.

4. Performance Metrics

Every execution outcome includes a duration_ms field. This metric is calculated using high-resolution monotonic clocks (time.perf_counter_ns) to provide precise data for bottleneck analysis in complex AI pipelines.

outcome \= runner.run(flow, ctx)
print(f"Total Latency: {outcome.duration_ms}ms")

5. Summary Table

Feature SyncRunner AsyncRunner
Primary Use Case Local ETL / CPU tasks Web APIs / LLM calls / Bots
Mixed Blocks No (Raises Error) Yes (Sync & Async)
Timeout Mechanism ThreadPool (Managed) Native asyncio.wait_for
Complexity Low Medium (Requires Event Loop)

Engineered with precision by AA Digital Business. High-end AI Architecture.