Skip to content

Execution Envelopes

Secure containers that wrap AI agent actions with governance, auditing, and budget controls.


What is an Envelope?

An envelope is the fundamental unit of execution in Fulcrum. Every AI agent action—whether reading a file, calling an API, or generating content—is wrapped in an envelope that provides:

  • Policy Enforcement: Rules checked before execution
  • Budget Tracking: Cost limits enforced in real-time
  • Audit Trail: Complete history of what happened
  • State Management: Clear lifecycle from creation to completion

Think of envelopes like a secure transaction wrapper: they ensure every agent action is authorized, budgeted, and recorded.


Why Envelopes Matter

Without governance, AI agents operate as black boxes:

Problem Envelope Solution
Unauthorized actions Policy check on every execution
Cost overruns Budget verification before approval
No audit trail Complete event log with timestamps
Runaway processes State machine with terminal states
Data breaches Tenant isolation via RLS

Envelope Lifecycle

Every envelope follows a defined state machine:

                    ┌─────────────┐
                    │   PENDING   │
                    └──────┬──────┘
              ┌────────────┼────────────┐
              ▼            ▼            ▼
       ┌──────────┐ ┌──────────┐ ┌──────────┐
       │AUTHORIZED│ │  DENIED  │ │CANCELLED │
       └────┬─────┘ └──────────┘ └──────────┘
            │           (final)     (final)
       ┌──────────┐
       │  ACTIVE  │
       └────┬─────┘
       ┌────┼────┐
       ▼         ▼
  ┌──────────┐ ┌──────────┐
  │COMPLETED │ │  FAILED  │
  └──────────┘ └──────────┘
   (final)      (final)

States Explained

State Meaning
PENDING Envelope created, awaiting policy evaluation
AUTHORIZED Policies passed, ready to execute
DENIED Policy violation—action blocked
ACTIVE Currently executing
COMPLETED Finished successfully
FAILED Execution error occurred
CANCELLED Manually stopped or timed out

How Envelopes Work

1. Creation

When an AI agent wants to perform an action, the SDK creates an envelope:

from fulcrum import FulcrumClient

client = FulcrumClient(host="localhost:50051")

with client.envelope(workflow_id="support-agent") as env:
    # Envelope is automatically created and authorized
    print(f"Envelope ID: {env.id}")
    print(f"Status: {env.status}")

2. Policy Check

Fulcrum evaluates all applicable policies:

  • Tool restrictions (e.g., "no bash commands")
  • Budget limits (e.g., "max $0.10 per request")
  • Rate limits (e.g., "max 60 requests/minute")
  • Custom rules (e.g., "require approval for deletions")

3. Execution

If authorized, the envelope moves to ACTIVE:

with client.envelope(workflow_id="support-agent") as env:
    if env.guard("send_email", input_text=message):
        # Action allowed—proceed
        send_email(message)
        env.log("email_sent", {"recipient": user.email})
    else:
        # Action blocked by policy
        env.log("action_blocked", {"reason": env.last_denial_reason})

4. Completion

The envelope automatically completes when the context exits:

with client.envelope(workflow_id="support-agent") as env:
    # ... do work ...
# Envelope automatically marked COMPLETED

Envelope Data

Each envelope captures rich metadata:

Field Description
envelope_id Unique identifier (UUID)
tenant_id Organization that owns this execution
workflow_id Logical grouping (e.g., "support-bot")
adapter_type Integration type (mcp, langchain, sdk)
budget_id Associated budget for cost tracking
status Current state
metadata Custom key-value pairs
created_at When the envelope was created
updated_at Last state transition

Multi-Tenancy

Envelopes enforce strict tenant isolation using PostgreSQL Row-Level Security:

  • Each envelope belongs to exactly one tenant
  • Queries automatically filter by tenant
  • Cross-tenant access is impossible at the database level
-- RLS policy ensures isolation
CREATE POLICY tenant_isolation ON envelopes
    USING (tenant_id = current_setting('fulcrum.current_tenant')::uuid);

Integration Patterns

Python SDK

with client.envelope(workflow_id="my-agent") as env:
    # Check before each action
    if env.guard("read_file", input_text=filename):
        content = read_file(filename)

    # Log events for audit
    env.log("file_read", {"path": filename})

TypeScript SDK

const envelope = client.envelope({ workflowId: 'my-agent' });

if (await envelope.guard('read_file', filename)) {
  const content = await readFile(filename);
}

await envelope.complete();

MCP Integration

When using the Fulcrum MCP server, envelopes are created automatically for each tool call. The MCP server:

  1. Creates an envelope for the tool invocation
  2. Evaluates policies for that tool
  3. Returns ALLOW/DENY to the agent
  4. Logs the complete execution

Best Practices

  1. One envelope per logical action - Don't reuse envelopes across unrelated work
  2. Use workflow IDs - Group related envelopes for easier analysis
  3. Log meaningful events - Include context that helps with debugging
  4. Handle denials gracefully - Provide useful feedback when actions are blocked
  5. Set budget associations - Link envelopes to budgets for cost control


Document Version: 1.0 Last Updated: January 20, 2026