Skip to main content
Last updated on

Temporal Plugin (Python)

OpenBoxPlugin is the sole public OpenBox integration entry point for Temporal Python. Add it to the native Worker's plugins list for governance, observability, and optional governed sandbox commands.

GuideDescription
Integration WalkthroughStep-by-step guide for adding OpenBox to Temporal workers
ConfigurationPlugin options and environment variables
Error HandlingHandle governance decisions and failures in your code
Governed Sandbox CommandsRegister one-attempt commands for enforced sandbox execution
Customizing the DemoTailor governance behavior to your agent's needs
Demo ArchitectureArchitecture of the reference demo application
TroubleshootingCommon issues and fixes for Temporal plugin setup
What the Plugin Does

The plugin's primary job is to connect your Temporal worker to OpenBox and send workflow/activity events to the platform. All trust logic, policies, and UI management happens on the platform. It does not happen in the plugin.

Philosophy

The plugin is intentionally minimal:

  • One plugin added to your existing native Worker
  • Plugin-owned setup for Worker interception, Workflows, and Activities
  • Zero OpenBox setup in Workflow and Activity code
  • One sandbox option on the same plugin for governed command interception
  • Automatic telemetry: captures HTTP, database, and file I/O operations
  • Composable: works alongside other Temporal plugins (e.g., OpenTelemetryPlugin)

Supported Engines

EngineLanguageStatus
TemporalPython✅ Supported
n8nJavaScript✅ Supported

Installation and Setup

See:

  1. Wrap an Existing Agent: Add OpenBox to an existing Temporal worker
  2. Temporal (Python): End-to-end setup from scratch
  3. Configuration: All plugin options

Plugin Usage

from openbox import OpenBoxPlugin
from openbox.sandbox import SandboxConfig

OpenBoxPlugin(
openbox_url: str,
openbox_api_key: str,
sandbox: SandboxConfig | None = None,
# + governance and instrumentation options
)

Add it to your Worker's plugins list:

worker = Worker(
client,
task_queue="my-task-queue",
workflows=[MyWorkflow],
activities=[my_activity],
plugins=[OpenBoxPlugin(
openbox_url=os.getenv("OPENBOX_URL"),
openbox_api_key=os.getenv("OPENBOX_API_KEY"),
)],
)

The plugin internally owns governance interceptors, OTel instrumentation, Workflow sandbox passthrough, and OpenBox lifecycle reporting. Supplying sandbox=SandboxConfig(...) on that same initializer enables governed-command interception for registered user Activities; see Governed Sandbox Commands.

See Configuration for the full parameter list.

What the Plugin Captures

The plugin automatically captures and sends to OpenBox:

Workflow Events

  • Workflow started/completed/failed
  • Signal received
  • Query executed

Activity Events

  • Activity started (with input)
  • Activity completed (with output and duration)
  • Activity failed (with error)

HTTP Telemetry

  • Request/response bodies (for LLM calls, external requests)
  • Headers and status codes
  • Request duration and timing

Database Operations (Optional)

  • SQL queries (PostgreSQL, MySQL)
  • NoSQL operations (MongoDB, Redis)

File I/O (Optional)

  • File read/write operations
  • File paths and sizes

All captured data is evaluated against your trust policies on the OpenBox platform.

Tracing

The @traced decorator wraps any function in an OpenTelemetry span so it appears in session replay. It works on both sync and async functions.

Import

from openbox.tracing import traced

Basic Usage

@traced
def process_data(input_data):
return transform(input_data)

@traced
async def fetch_data(url):
return await http_get(url)

With Options

@traced(
name="custom-span-name",
capture_args=True, # Capture function arguments (default: True)
capture_result=True, # Capture return value (default: True)
capture_exception=True, # Capture exception details on error (default: True)
max_arg_length=2000, # Max length for serialized arguments (default: 2000)
)
async def process_sensitive_data(data):
return await handle(data)

Manual Spans

For more control, use create_span as a context manager:

from openbox.tracing import create_span

with create_span("my-operation", {"input": data}) as span:
result = do_something()
span.set_attribute("output", result)

How It Works

Governed-command API

SymbolImportPurpose
OpenBoxPluginopenbox.pluginSole Temporal integration entry point
SandboxConfigopenbox.sandbox.configConfigure registered governed commands through OpenBoxPlugin(..., sandbox=...)
GovernedCommandRegistry and typed definitionsopenbox.sandboxDefine bounded command profiles and typed results

Only registered governed commands can enforce CONSTRAIN through sandbox execution. Policy routing uses constraints: ["run_in_sandbox"]; a behavioral CONSTRAIN can select a registered replacement profile and abort the triggering host action. An ordinary Temporal action that receives an unsupported CONSTRAIN fails closed rather than continuing as if it received ALLOW. The plugin owns bounded history conversion, output mapping, and cancellation cleanup, while the dispatcher enforces at-most-once dispatch per dispatch ID.

The sandbox runtime defaults to the native provider (sandbox-exec on macOS, bubblewrap on Linux). See Governed Sandbox Commands for plugin composition, provisioning, runtime evidence, and zero-host requirements.

Configuration

See Configuration for all options including:

  • Environment variables
  • Governance timeout and fail policies
  • Event filtering (skip workflows/activities)
  • Database and file I/O instrumentation

Next Steps

  1. Temporal Integration - Add OpenBox to an existing Temporal agent
  2. Configuration - Configure timeouts, fail policies, and exclusions
  3. Governed Sandbox Commands - Enforce constrained registered commands in isolation
  4. Error Handling - Handle governance decisions in your code