Skip to content

Fulcrum API Overview

Comprehensive reference for Fulcrum's gRPC-first API architecture

Version: 2.0.0 Last Updated: January 6, 2026 Status: Production


Table of Contents

  1. API Design Philosophy
  2. Authentication
  3. Service Catalog
  4. Rate Limiting
  5. Error Handling
  6. Quick Start Examples
  7. Protocol Buffers Reference
  8. Best Practices

API Design Philosophy

Fulcrum follows a gRPC-first architecture with an HTTP/REST gateway for broader compatibility. This approach delivers:

Why gRPC-First?

Characteristic Benefit
Binary Protocol (Protobuf) 10x smaller payloads vs JSON, critical for high-volume event streaming
Strongly Typed Contracts Compile-time safety, auto-generated SDKs, self-documenting
Bidirectional Streaming Real-time event subscriptions for Mission Tape UI
HTTP/2 Multiplexing Multiple concurrent requests over single connection
Native Code Generation First-class Go, Python, TypeScript SDKs from single source

API Architecture

                        +------------------+
                        |   Client Apps    |
                        | (Dashboard, SDK) |
                        +--------+---------+
                                 |
              +------------------+------------------+
              |                                     |
      +-------v-------+                    +-------v-------+
      |   gRPC API    |                    | REST Gateway  |
      | :50051 (TLS)  |                    |  :8080 (HTTP) |
      +-------+-------+                    +-------+-------+
              |                                    |
              | Protocol Buffers                   | JSON
              |                                    |
      +-------v------------------------------------v-------+
      |              Fulcrum Service Layer                 |
      |  +----------+ +----------+ +----------+ +--------+ |
      |  | Policy   | | Cost     | | Event    | | Brain  | |
      |  | Engine   | | Engine   | | Store    | | (LLM)  | |
      |  +----------+ +----------+ +----------+ +--------+ |
      +---------------------------------------------------+

Endpoint Conventions

Protocol Endpoint Use Case
gRPC grpc://localhost:50051 SDKs, service-to-service, high-performance
gRPC-Web https://api.fulcrum.dev/grpc Browser clients with gRPC-Web proxy
REST https://api.fulcrum.dev/v1/* Legacy systems, webhooks, debugging

Versioning Strategy

Fulcrum uses package-level versioning in Protocol Buffers:

package fulcrum.policy.v1;     // Current stable
package fulcrum.policy.v2;     // Next major (when needed)
  • v1: Stable, production-ready, breaking changes avoided
  • Beta features: Marked with (beta) suffix in method names
  • Deprecation: Minimum 6-month notice before removal

Authentication

Fulcrum uses API key authentication with tenant context for multi-tenant isolation.

Authentication Flow

+--------+         +------------+         +-----------+
| Client |         | Fulcrum    |         | Tenant    |
|        |         | Gateway    |         | Store     |
+---+----+         +-----+------+         +-----+-----+
    |                    |                      |
    | 1. Request with    |                      |
    |    x-api-key       |                      |
    +------------------->|                      |
    |                    |                      |
    |                    | 2. SHA256 hash key   |
    |                    | 3. Lookup hash       |
    |                    +--------------------->|
    |                    |                      |
    |                    | 4. Return tenant_id  |
    |                    |    + scopes          |
    |                    |<---------------------+
    |                    |                      |
    |                    | 5. Inject context    |
    |                    |    into request      |
    |                    |                      |
    | 6. Response        |                      |
    |<-------------------+                      |

API Key Management

Create and manage API keys via the TenantService:

service TenantService {
  // Create a new API key for the authenticated tenant
  rpc CreateApiKey(CreateApiKeyRequest) returns (CreateApiKeyResponse);

  // List all API keys for the tenant
  rpc ListApiKeys(ListApiKeysRequest) returns (ListApiKeysResponse);

  // Revoke an API key by ID
  rpc RevokeApiKey(RevokeApiKeyRequest) returns (RevokeApiKeyResponse);
}

Authentication Headers

gRPC

// Go
md := metadata.Pairs("x-api-key", "flcm_live_xxxxxxxxxxxx")
ctx := metadata.NewOutgoingContext(context.Background(), md)
# Python
metadata = [("x-api-key", "flcm_live_xxxxxxxxxxxx")]
response = stub.EvaluatePolicy(request, metadata=metadata)
// TypeScript
const metadata = new grpc.Metadata();
metadata.add('x-api-key', 'flcm_live_xxxxxxxxxxxx');

REST

curl -H "X-Api-Key: flcm_live_xxxxxxxxxxxx" \
     https://api.fulcrum.dev/v1/policies

API Key Format

Prefix Environment Example
flcm_live_ Production flcm_live_abc123def456...
flcm_test_ Sandbox/Testing flcm_test_xyz789abc012...
flcm_dev_ Development flcm_dev_dev123local...

Scopes

API keys can be scoped to limit access:

Scope Description
* Full administrative access
policies:read Read policies
policies:write Create/update/delete policies
envelopes:read Read execution envelopes
envelopes:write Create/update envelopes
costs:read View cost data
budgets:write Manage budgets
events:read Query event store
brain:evaluate Use cognitive services

Tenant Context

Every authenticated request automatically receives tenant context:

// Server-side: Extract tenant from authenticated context
tenantID, ok := middleware.GetTenantID(ctx)
if !ok {
    return status.Error(codes.Unauthenticated, "tenant context required")
}

PostgreSQL Row-Level Security (RLS) enforces tenant isolation at the database level:

-- All queries automatically filtered by tenant
SET fulcrum.current_tenant = 'tenant-uuid';
SELECT * FROM policies;  -- Only returns tenant's policies

Service Catalog

Fulcrum exposes nine gRPC services organized into three functional domains:

Core Governance Services

PolicyService

Package: fulcrum.policy.v1 Purpose: Policy management and real-time evaluation Latency Target: <10ms P99

service PolicyService {
  // Policy CRUD
  rpc CreatePolicy(CreatePolicyRequest) returns (CreatePolicyResponse);
  rpc GetPolicy(GetPolicyRequest) returns (GetPolicyResponse);
  rpc UpdatePolicy(UpdatePolicyRequest) returns (UpdatePolicyResponse);
  rpc DeletePolicy(DeletePolicyRequest) returns (DeletePolicyResponse);
  rpc ListPolicies(ListPoliciesRequest) returns (ListPoliciesResponse);

  // Evaluation (critical path)
  rpc EvaluatePolicy(EvaluatePolicyRequest) returns (EvaluatePolicyResponse);
  rpc EvaluatePolicies(EvaluatePoliciesRequest) returns (EvaluatePoliciesResponse);
  rpc GetEvaluationHistory(GetEvaluationHistoryRequest) returns (GetEvaluationHistoryResponse);

  // Approval Workflow
  rpc ListApprovals(ListApprovalsRequest) returns (ListApprovalsResponse);
  rpc UpdateApproval(UpdateApprovalRequest) returns (UpdateApprovalResponse);
}

Key Concepts: - Policy Rules: Define conditions and actions (ALLOW, DENY, WARN, REQUIRE_APPROVAL) - Enforcement Levels: AUDIT (log only), WARN, BLOCK, TERMINATE - Condition Types: Field match, regex, semantic (LLM-based), statistical spike - Execution Phases: PRE_EXECUTION, PRE_LLM_CALL, POST_LLM_CALL, PRE_TOOL_CALL, POST_TOOL_CALL, POST_EXECUTION

CostService

Package: fulcrum.cost.v1 Purpose: Budget management and cost tracking Latency Target: <5ms P99

service CostService {
  // Budget CRUD
  rpc CreateBudget(CreateBudgetRequest) returns (CreateBudgetResponse);
  rpc GetBudget(GetBudgetRequest) returns (GetBudgetResponse);
  rpc UpdateBudget(UpdateBudgetRequest) returns (UpdateBudgetResponse);
  rpc DeleteBudget(DeleteBudgetRequest) returns (DeleteBudgetResponse);
  rpc ListBudgets(ListBudgetsRequest) returns (ListBudgetsResponse);

  // Cost Analytics
  rpc GetCostSummary(GetCostSummaryRequest) returns (GetCostSummaryResponse);
  rpc GetSpendSummary(GetSpendSummaryRequest) returns (GetSpendSummaryResponse);
  rpc GetBudgetStatus(GetBudgetStatusRequest) returns (GetBudgetStatusResponse);

  // Prediction
  rpc PredictCost(PredictCostRequest) returns (PredictCostResponse);
}

Key Concepts: - Budget Periods: Hourly, daily, weekly, monthly, quarterly, yearly, custom - Notification Thresholds: Configurable alerts at percentage milestones (e.g., 80%, 95%) - Budget Status: OK, WARNING, CRITICAL, EXCEEDED, SUSPENDED - Spend Aggregation: By model, by day/week/month, by workflow

EnvelopeService

Package: fulcrum.envelope.v1 Purpose: Execution envelope lifecycle management Latency Target: <5ms P99

service EnvelopeService {
  // Lifecycle management
  rpc CreateEnvelope(CreateEnvelopeRequest) returns (CreateEnvelopeResponse);
  rpc GetEnvelope(GetEnvelopeRequest) returns (GetEnvelopeResponse);
  rpc UpdateEnvelopeStatus(UpdateEnvelopeStatusRequest) returns (UpdateEnvelopeStatusResponse);
}

Key Concepts: - Execution Envelope (EEV): Core abstraction wrapping all agent executions - Status Lifecycle: PENDING -> AUTHORIZED -> RUNNING -> COMPLETED/FAILED/TERMINATED - Framework Support: LangGraph, Microsoft Semantic Kernel, CrewAI, AutoGen, Custom

Cognitive Services (Brain)

SemanticJudgeService

Package: fulcrum.brain.v1 Purpose: LLM-based intent evaluation and risk classification Latency Target: <50ms P99

service SemanticJudgeService {
  // Evaluate policy conditions using LLM semantic analysis
  rpc EvaluateCondition(EvaluateConditionRequest) returns (EvaluateConditionResponse);

  // Classify risk level of agent actions
  rpc ClassifyRisk(ClassifyRiskRequest) returns (ClassifyRiskResponse);

  // Derive intent from pattern signatures
  rpc DeriveIntent(DeriveIntentRequest) returns (DeriveIntentResponse);
}

Key Concepts: - Local LLM Inference: Uses Ollama (llama3.2) for privacy-preserving evaluation - Fallback Mode: Deterministic evaluation if LLM fails - Risk Levels: LOW, MEDIUM, HIGH, CRITICAL - Confidence Scoring: 0.0-1.0 confidence threshold for semantic matches

OracleService

Package: fulcrum.brain.v1 Purpose: Predictive cost modeling (unique differentiator) Latency Target: <20ms P99

service OracleService {
  // Predict budget overrun probability
  rpc PredictBudgetOverrun(PredictOverrunRequest) returns (PredictOverrunResponse);

  // Get/rebuild prediction models
  rpc GetPredictionModel(GetPredictionModelRequest) returns (GetPredictionModelResponse);
  rpc ListPredictionModels(ListPredictionModelsRequest) returns (ListPredictionModelsResponse);
}

Key Concepts: - Statistical Models: Built from historical execution data - Overrun Probability: 0.0-1.0 probability of exceeding budget - Recommended Actions: NONE, WARN, REDUCE_RATE, REQUEST_QUOTA, HALT - Model Metrics: avg_cost_per_run, std_dev, runs_per_hour, sample_size

ImmuneSystemService

Package: fulcrum.brain.v1 Purpose: Automated policy generation from incident patterns Latency Target: <100ms P99

service ImmuneSystemService {
  // Report incidents for learning
  rpc ReportIncident(ReportIncidentRequest) returns (ReportIncidentResponse);

  // Pattern detection
  rpc GetAttackPatterns(GetAttackPatternsRequest) returns (GetAttackPatternsResponse);

  // Auto-generated policy management
  rpc GetPendingPolicies(GetPendingPoliciesRequest) returns (GetPendingPoliciesResponse);
  rpc ReviewGeneratedPolicy(ReviewGeneratedPolicyRequest) returns (ReviewGeneratedPolicyResponse);

  // Incident history
  rpc ListIncidents(ListIncidentsRequest) returns (ListIncidentsResponse);
}

Key Concepts: - Incident Categories: Budget overrun, policy violation, security breach, rate limit exceeded, anomaly detected - Attack Patterns: Automatically detected from incident correlation - Generated Policies: Human-in-the-loop review before activation - Auto-Activation: High-confidence policies can activate without approval

Infrastructure Services

CheckpointService

Package: fulcrum.checkpoint.v1 Purpose: Execution state persistence and recovery Latency Target: <10ms P99

service CheckpointService {
  // Checkpoint CRUD
  rpc SaveCheckpoint(SaveCheckpointRequest) returns (SaveCheckpointResponse);
  rpc GetCheckpoint(GetCheckpointRequest) returns (GetCheckpointResponse);
  rpc ListCheckpoints(ListCheckpointsRequest) returns (ListCheckpointsResponse);
  rpc DeleteCheckpoint(DeleteCheckpointRequest) returns (DeleteCheckpointResponse);

  // Version management
  rpc ListCheckpointVersions(ListCheckpointVersionsRequest) returns (ListCheckpointVersionsResponse);
  rpc GetCheckpointVersion(GetCheckpointVersionRequest) returns (GetCheckpointVersionResponse);

  // Query and context
  rpc QueryCheckpoints(QueryCheckpointsRequest) returns (QueryCheckpointsResponse);
  rpc GetExecutionContext(GetExecutionContextRequest) returns (GetExecutionContextResponse);
  rpc UpdateExecutionContext(UpdateExecutionContextRequest) returns (UpdateExecutionContextResponse);
}

Key Concepts: - Checkpoint Types: Manual, auto, pre-terminate, error, milestone - Version Chains: Parent-child relationships for version history - Context Scopes: Execution, workflow, tenant-wide - Merge Strategies: Last-write-wins, fail-on-conflict, recursive merge

EventStoreService

Package: fulcrum.eventstore.v1 Purpose: Event persistence and real-time streaming Latency Target: <5ms P99 (publish), <50ms P99 (query)

service EventStoreService {
  // Publishing
  rpc PublishEvent(PublishEventRequest) returns (PublishEventResponse);
  rpc PublishEventBatch(PublishEventBatchRequest) returns (PublishEventBatchResponse);

  // Querying
  rpc QueryEvents(QueryEventsRequest) returns (QueryEventsResponse);
  rpc GetExecutionEvents(GetExecutionEventsRequest) returns (GetExecutionEventsResponse);

  // Real-time streaming
  rpc StreamEvents(StreamEventsRequest) returns (stream StreamEventsResponse);

  // Statistics
  rpc GetEventStoreStats(GetEventStoreStatsRequest) returns (GetEventStoreStatsResponse);
}

Key Concepts: - Event Types: Execution lifecycle, LLM calls, tool invocations, checkpoints, budget, policy - NATS JetStream: Durable event streaming with replay capability - TimescaleDB: High-resolution time-series storage - Retention Policies: Configurable per event type and tenant

TenantService

Package: fulcrum.tenant.v1 Purpose: Tenant and API key management Latency Target: <10ms P99

service TenantService {
  rpc CreateApiKey(CreateApiKeyRequest) returns (CreateApiKeyResponse);
  rpc ListApiKeys(ListApiKeysRequest) returns (ListApiKeysResponse);
  rpc RevokeApiKey(RevokeApiKeyRequest) returns (RevokeApiKeyResponse);
}

Service Summary Matrix

Service Package Primary Use Latency P99
PolicyService policy.v1 Policy evaluation <10ms
CostService cost.v1 Budget management <5ms
EnvelopeService envelope.v1 Execution lifecycle <5ms
SemanticJudgeService brain.v1 LLM-based evaluation <50ms
OracleService brain.v1 Cost prediction <20ms
ImmuneSystemService brain.v1 Auto-policy generation <100ms
CheckpointService checkpoint.v1 State persistence <10ms
EventStoreService eventstore.v1 Event streaming <5ms
TenantService tenant.v1 API key management <10ms

Rate Limiting

Fulcrum implements tenant-aware rate limiting using Redis-backed token buckets.

Default Limits

Tier Requests/Second Burst Capacity
Developer (Free) 10 20
Pro 100 200
Team 500 1,000
Enterprise Custom Custom

Rate Limit Headers

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1704499200

Rate Limit Response

When limits are exceeded:

gRPC:

Status: RESOURCE_EXHAUSTED (8)
Message: "rate limit exceeded"

REST:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 60

{
  "code": 8,
  "message": "rate limit exceeded",
  "details": []
}

Rate Limit Implementation

// From internal/middleware/ratelimit.go
type RateLimitInterceptor struct {
    limiter         *ratelimit.Limiter
    defaultRate     float64  // 10.0 requests per second
    defaultCapacity int      // Burst of 20
}

Fail-Open Policy

Rate limiting fails open to prevent governance from blocking critical paths:

allowed, err := i.limiter.Allow(ctx, key, rate, capacity, 1)
if err != nil {
    // Fail open: allow request on Redis failure
    return handler(ctx, req)
}

Error Handling

Fulcrum uses standard gRPC status codes with structured error details.

gRPC Status Codes

Code Name HTTP Description
0 OK 200 Success
3 INVALID_ARGUMENT 400 Invalid request parameters
5 NOT_FOUND 404 Resource not found
7 PERMISSION_DENIED 403 Insufficient permissions
8 RESOURCE_EXHAUSTED 429 Rate limit exceeded
13 INTERNAL 500 Internal server error
14 UNAVAILABLE 503 Service temporarily unavailable
16 UNAUTHENTICATED 401 Invalid or missing authentication

Error Response Structure

gRPC:

message Status {
  int32 code = 1;
  string message = 2;
  repeated google.protobuf.Any details = 3;
}

REST (JSON):

{
  "code": 7,
  "message": "policy evaluation denied action",
  "details": [
    {
      "@type": "type.googleapis.com/fulcrum.policy.v1.EvaluationResult",
      "policy_id": "pol_abc123",
      "decision": "DENY",
      "matched_rules": [
        {
          "rule_id": "rule_xyz",
          "rule_name": "block_sensitive_data",
          "matched_conditions": ["content_filter"]
        }
      ],
      "message": "PII detected in output"
    }
  ]
}

Domain-Specific Errors

Policy Errors

// Policy violation returns PERMISSION_DENIED with EvaluationResult details
message EvaluationResult {
  string policy_id = 1;
  EvaluationDecision decision = 2;
  repeated RuleMatch matched_rules = 3;
  string message = 5;
}

Budget Errors

// Budget exceeded returns RESOURCE_EXHAUSTED with BudgetStatus details
message BudgetStatus {
  string budget_id = 1;
  BudgetStatusType status = 2;  // EXCEEDED
  float cost_usage_percent = 4;
  BudgetLimits remaining = 7;
}

Authentication Errors

// From internal/middleware/auth.go
if len(keys) == 0 {
    return nil, status.Error(codes.Unauthenticated, "x-api-key is required")
}

if errors.Is(err, tenant.ErrTenantNotFound) {
    return nil, status.Error(codes.Unauthenticated, "invalid api key")
}

Error Handling Best Practices

  1. Always check status codes: Don't assume success
  2. Parse error details: Extract domain-specific context
  3. Implement retry logic: For UNAVAILABLE and rate limit errors
  4. Log error details: Include trace_id for debugging
  5. Configure failure modes: FAIL_OPEN vs FAIL_CLOSED per use case

Quick Start Examples

Go

package main

import (
    "context"
    "log"

    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    "google.golang.org/grpc/metadata"

    policyv1 "github.com/fulcrum-io/fulcrum/pkg/policy/v1"
    envelopev1 "github.com/fulcrum-io/fulcrum/pkg/envelope/v1"
)

func main() {
    // Connect to Fulcrum
    conn, err := grpc.Dial(
        "localhost:50051",
        grpc.WithTransportCredentials(insecure.NewCredentials()),
    )
    if err != nil {
        log.Fatalf("failed to connect: %v", err)
    }
    defer conn.Close()

    // Create clients
    envelopeClient := envelopev1.NewEnvelopeServiceClient(conn)
    policyClient := policyv1.NewPolicyServiceClient(conn)

    // Add authentication
    ctx := metadata.NewOutgoingContext(
        context.Background(),
        metadata.Pairs("x-api-key", "flcm_live_xxxxxxxxxxxx"),
    )

    // Create execution envelope
    envelope, err := envelopeClient.CreateEnvelope(ctx, &envelopev1.CreateEnvelopeRequest{
        TenantId:    "tenant-123",
        AdapterType: "custom",
        Metadata: map[string]string{
            "workflow": "customer-support",
            "user_id":  "user-456",
        },
    })
    if err != nil {
        log.Fatalf("failed to create envelope: %v", err)
    }

    log.Printf("Created envelope: %s", envelope.Envelope.EnvelopeId)

    // Evaluate policy before action
    evalResult, err := policyClient.EvaluatePolicies(ctx, &policyv1.EvaluatePoliciesRequest{
        Context: &policyv1.EvaluationContext{
            TenantId:    "tenant-123",
            EnvelopeId:  envelope.Envelope.EnvelopeId,
            Phase:       policyv1.ExecutionPhase_EXECUTION_PHASE_PRE_TOOL_CALL,
            ToolNames:   []string{"send_email"},
            InputText:   "Send report to user@example.com",
        },
        StopOnDeny: true,
    })
    if err != nil {
        log.Fatalf("policy evaluation failed: %v", err)
    }

    switch evalResult.FinalDecision {
    case policyv1.EvaluationDecision_EVALUATION_DECISION_ALLOW:
        log.Println("Action allowed - proceeding")
        // Execute the action
    case policyv1.EvaluationDecision_EVALUATION_DECISION_DENY:
        log.Printf("Action denied: %s", evalResult.Results[0].Message)
    case policyv1.EvaluationDecision_EVALUATION_DECISION_REQUIRE_APPROVAL:
        log.Println("Action requires human approval")
    }
}

Python

from fulcrum import FulcrumClient, FailureMode
from fulcrum.exceptions import PolicyViolationError, BudgetExceededError

# Initialize client
client = FulcrumClient(
    host="localhost:50051",
    api_key="flcm_live_xxxxxxxxxxxx",
    on_failure=FailureMode.FAIL_OPEN,
    timeout_ms=500,
)

# Alternative: Initialize from environment variables
# client = FulcrumClient.from_env()

def run_governed_agent(user_query: str) -> str:
    """Execute an agent action with Fulcrum governance."""

    # Create governance envelope
    with client.envelope(
        workflow_id="customer-support-bot",
        metadata={"source": "api", "priority": "normal"}
    ) as env:

        # Pre-execution policy check
        if not env.guard("process_query", input_text=user_query):
            return "Query blocked by policy"

        # Simulate agent processing
        response = process_with_llm(user_query)

        # Check tool usage before execution
        if needs_email(response):
            if env.guard("send_email", input_text=response):
                send_email(response)
                env.log("email_sent", {"status": "success"})
            else:
                env.log("email_blocked", {"reason": "policy"})

        # Get cost summary
        cost = env.get_cost()
        print(f"Execution cost: ${cost.total_usd:.4f}")

        return response

# Error handling example
try:
    result = run_governed_agent("Summarize sales report")
    print(f"Result: {result}")
except PolicyViolationError as e:
    print(f"Policy violation: {e.policy_id} - {e.message}")
except BudgetExceededError as e:
    print(f"Budget exceeded: ${e.current_spend:.2f} of ${e.budget_limit:.2f}")
except Exception as e:
    print(f"Error: {e}")

TypeScript

import { FulcrumClient, FailureMode } from '@fulcrum-governance/sdk';
import { PolicyViolationError, BudgetExceededError } from '@fulcrum-governance/sdk/errors';

// Initialize client
const client = new FulcrumClient({
  host: 'localhost:50051',
  apiKey: 'flcm_live_xxxxxxxxxxxx',
  onFailure: FailureMode.FAIL_OPEN,
  timeoutMs: 500,
});

// Alternative: Initialize from environment
// const client = FulcrumClient.fromEnv();

async function runGovernedAgent(userQuery: string): Promise<string> {
  // Create governance envelope
  const envelope = client.envelope({
    workflowId: 'customer-support-bot',
    metadata: { source: 'api', priority: 'normal' },
  });

  try {
    // Pre-execution policy check
    if (!await envelope.guard('process_query', userQuery)) {
      return 'Query blocked by policy';
    }

    // Simulate agent processing
    const response = await processWithLLM(userQuery);

    // Check tool usage before execution
    if (needsEmail(response)) {
      if (await envelope.guard('send_email', response)) {
        await sendEmail(response);
        envelope.log('email_sent', { status: 'success' });
      } else {
        envelope.log('email_blocked', { reason: 'policy' });
      }
    }

    // Get cost summary
    const cost = await envelope.getCost();
    console.log(`Execution cost: $${cost.totalUsd.toFixed(4)}`);

    // Complete envelope
    await envelope.complete({ result: response });

    return response;
  } catch (error) {
    if (error instanceof PolicyViolationError) {
      console.error(`Policy violation: ${error.policyId} - ${error.message}`);
      throw error;
    }
    if (error instanceof BudgetExceededError) {
      console.error(`Budget exceeded: $${error.currentSpend} of $${error.budgetLimit}`);
      throw error;
    }
    throw error;
  }
}

// Usage
runGovernedAgent('Summarize sales report')
  .then(result => console.log(`Result: ${result}`))
  .catch(err => console.error(`Error: ${err.message}`));

cURL (REST)

# Health check
curl http://localhost:8080/healthz

# Create envelope
curl -X POST http://localhost:8080/v1/envelopes \
  -H "X-Api-Key: flcm_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tenant_id": "tenant-123",
    "adapter_type": "custom",
    "metadata": {
      "workflow": "customer-support"
    }
  }'

# Evaluate policies
curl -X POST http://localhost:8080/v1/policies/batch-evaluate \
  -H "X-Api-Key: flcm_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "context": {
      "tenant_id": "tenant-123",
      "envelope_id": "env-abc123",
      "phase": "EXECUTION_PHASE_PRE_TOOL_CALL",
      "tool_names": ["send_email"],
      "input_text": "Send report to user@example.com"
    },
    "stop_on_deny": true
  }'

# List policies
curl http://localhost:8080/v1/policies?tenant_id=tenant-123 \
  -H "X-Api-Key: flcm_live_xxxxxxxxxxxx"

# Get budget status
curl http://localhost:8080/v1/budgets/budget-xyz/status \
  -H "X-Api-Key: flcm_live_xxxxxxxxxxxx"

# Predict cost
curl -X POST http://localhost:8080/v1/costs/predict \
  -H "X-Api-Key: flcm_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tenant_id": "tenant-123",
    "workflow_id": "customer-support",
    "model_ids": ["gpt-4", "claude-3-opus"],
    "use_historical_data": true,
    "lookback_days": 7
  }'

Protocol Buffers Reference

File Locations

proto/fulcrum/
├── brain/v1/
│   └── brain_service.proto      # Cognitive services (SemanticJudge, Oracle, ImmuneSystem)
├── checkpoint/v1/
│   └── checkpoint_service.proto # State persistence
├── cost/v1/
│   └── cost_service.proto       # Budget and cost management
├── envelope/v1/
│   ├── envelope.proto           # Core envelope types
│   └── envelope_service.proto   # Envelope lifecycle
├── events/v1/
│   └── events.proto             # Normalized event schema
├── eventstore/v1/
│   └── eventstore.proto         # Event persistence and streaming
├── policy/v1/
│   └── policy_service.proto     # Policy management and evaluation
├── tenant/v1/
│   └── tenant_service.proto     # Tenant and API key management
└── bridge/v1/
    └── bridge.proto             # Python-Go bridge (LangGraph)

Code Generation

# Install buf CLI
brew install bufbuild/buf/buf

# Generate code for all languages
buf generate

# Lint proto files
buf lint

# Check for breaking changes
buf breaking --against '.git#branch=main'

Go Package Mapping

Proto Package Go Import Path
fulcrum.policy.v1 github.com/fulcrum-io/fulcrum/pkg/policy/v1
fulcrum.cost.v1 github.com/fulcrum-io/fulcrum/pkg/cost/v1
fulcrum.envelope.v1 github.com/fulcrum-io/fulcrum/pkg/envelope/v1
fulcrum.brain.v1 github.com/fulcrum-io/fulcrum/pkg/brain/v1
fulcrum.checkpoint.v1 github.com/fulcrum-io/fulcrum/pkg/checkpoint/v1
fulcrum.eventstore.v1 github.com/fulcrum-io/fulcrum/pkg/eventstore/v1
fulcrum.events.v1 github.com/fulcrum-io/fulcrum/pkg/events/v1
fulcrum.tenant.v1 github.com/fulcrum-io/fulcrum/pkg/tenant/v1

Best Practices

1. Fail-Safe Configuration

Choose the appropriate failure mode for your use case:

Mode Behavior Use Case
FAIL_OPEN Allow on error Non-critical governance, monitoring
FAIL_CLOSED Block on error High-security, compliance-critical
# Production: fail-closed for security
client = FulcrumClient(
    host="fulcrum.internal:50051",
    api_key=os.environ["FULCRUM_API_KEY"],
    on_failure=FailureMode.FAIL_CLOSED,
    timeout_ms=200,  # Low timeout for fast fail
)

2. Timeout Tuning

// Critical path: low timeout, fail-open
const criticalClient = new FulcrumClient({
  host: 'fulcrum.internal:50051',
  timeoutMs: 100,  // 100ms timeout
  onFailure: 'FAIL_OPEN',
});

// Background processing: higher timeout, fail-closed
const batchClient = new FulcrumClient({
  host: 'fulcrum.internal:50051',
  timeoutMs: 5000,  // 5s timeout
  onFailure: 'FAIL_CLOSED',
});

3. Connection Management

// Reuse connections - don't create per-request
var (
    conn   *grpc.ClientConn
    client policyv1.PolicyServiceClient
)

func init() {
    var err error
    conn, err = grpc.Dial(
        "fulcrum.internal:50051",
        grpc.WithTransportCredentials(insecure.NewCredentials()),
        grpc.WithKeepaliveParams(keepalive.ClientParameters{
            Time:                10 * time.Second,
            Timeout:             3 * time.Second,
            PermitWithoutStream: true,
        }),
    )
    if err != nil {
        log.Fatalf("failed to connect: %v", err)
    }
    client = policyv1.NewPolicyServiceClient(conn)
}

4. Batch Operations

# Prefer batch evaluation over multiple single calls
result = client.evaluate_policies(
    context={
        "tenant_id": tenant_id,
        "tool_names": ["tool1", "tool2", "tool3"],
    },
    stop_on_deny=True,  # Short-circuit on first deny
)

5. Event Logging

// Log business events for audit trail
envelope.log('customer_action', {
  action: 'refund_requested',
  amount: 150.00,
  currency: 'USD',
  customer_id: 'cust_123',
  agent_decision: 'approved',
});

6. Checkpoint Strategy

# Checkpoint at expensive operations
with client.envelope(workflow_id="long-running-analysis") as env:
    for i, chunk in enumerate(large_dataset):
        process(chunk)

        # Checkpoint every 100 items
        if i % 100 == 0:
            env.checkpoint()
            env.log("progress", {"processed": i})

7. Distributed Tracing

// Propagate trace context
import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/propagation"
)

func createEnvelopeWithTrace(ctx context.Context) {
    // Extract trace context
    carrier := propagation.MapCarrier{}
    otel.GetTextMapPropagator().Inject(ctx, carrier)

    // Pass to Fulcrum
    envelope, _ := envelopeClient.CreateEnvelope(ctx, &envelopev1.CreateEnvelopeRequest{
        TenantId: "tenant-123",
        Metadata: carrier,  // trace_id, span_id, etc.
    })
}


Support

  • Documentation: docs.fulcrum.dev
  • Email: support@fulcrum.dev
  • Enterprise: Contact your account representative

Last Updated: January 6, 2026 Fulcrum Version: 2.0.0