Home / Docs / Verifiable Execution

Verifiable Execution

Verifiable Execution

Verifiable execution records signed, tamper-evident timelines for agent messages, streamed events, LLM calls, tool calls, plugin calls, and external effects. It turns agent activity into durable evidence that can be verified later by your cluster, another FabrCore cluster, or an external audit process.

Core idea

Monitoring shows what happened. Verifiable execution proves the recorded timeline has not been changed and ties it to the runtime, agent type, plugin/tool version, prompt hash, model config hash, and signing identity that produced it.

Why It Exists

Agent systems are distributed decision systems. One user request can trigger agent-to-agent messages, event streams, LLM calls, tool invocations, plugin side effects, HTTP calls, database updates, and outbound responses. Conventional logs are useful, but they are not enough when a customer later asks whether a record was edited, whether a plugin call really belonged to an operation, or which runtime version produced an answer.

Verifiable execution gives the system a chain of custody. Like a flight recorder or a tamper-evident receipt, it records the important steps and makes later changes detectable.

Record Kinds

KindWhat it records
MessageInbound, MessageOutboundClient-to-agent, agent-to-agent, and response messages.
EventPublished, EventDelivered, EventHandledStreamed event publication, delivery, handler success, and nested event lineage.
AgentDispatch, AgentResponseAgent execution start and completion.
LlmCallModel call metadata, prompt hash, model config hash, response hash, token data, and errors.
ToolCall, PluginCallFunction invocation, argument hash, result hash, elapsed time, and failure state.
ExternalHttpCall, ExternalDbEffect, ExternalStorageEffect, ExternalLibraryCallAttested external side effects recorded through SDK helpers, provider audit, outbox integration, or manual evidence APIs.
Error, TerminalFailures and final operation status.

Lineage Model

TraceId is the operation id. SpanId identifies the current step. ParentSpanId links that step to the caller, message, event publisher, or handler that caused it.

Message and Event Lineage
AgentMessage
  Id
  TraceId          // operation id
  SpanId           // message span
  ParentSpanId     // caller or publisher span
  VerifiableExecution

EventMessage
  Id
  TraceId
  SpanId
  ParentSpanId
  VerifiableExecution

Outbound messages and events created inside OnMessage or OnEvent inherit the current operation context, so the final evidence bundle can reconstruct the whole causal graph.

Signing and Chaining

Each record is canonicalized, hashed, signed, and chained to the previous record in the operation. The signature envelope can travel compactly on AgentMessage and EventMessage, while the full evidence is stored by an IVerifiableExecutionStore.

  • Canonical hashing makes equivalent records produce the same digest.
  • Hash chaining makes edit, delete, insert, and reorder tampering detectable.
  • Runtime provenance ties evidence to host version, deployment id, agent alias, assembly version, config hash, prompt hash, and model config hash.
  • Verification can run online through host endpoints or offline from an exported operation bundle.

Setup Levels

LevelConfigurationBenefit
DefaultOffNo behavior change. Existing monitoring and telemetry continue unchanged.
EasyLocal signed executionFast path for signed evidence in development, staging, demos, and smaller deployments.
ProductionCertificate, KMS, or HSM signer plus SQL/custom storeDurable evidence storage, key protection, and rotation-friendly signing.
Enterprise / cross-clusterSPIFFE trust by defaultDefault workload-identity trust path for multi-cluster, multi-team, zero-trust, or external audit scenarios. Certificate, KMS, and HSM signers remain supported provider alternatives.

Easy Local Signing

Program.cs
builder.AddFabrCoreServer(options =>
{
    options.UseVerifiableExecution(verifiable =>
    {
        verifiable.Enabled = true;
        verifiable.CapturePayloadHashes = true;
    });

    options.UseLocalCertificateVerifiableExecutionSigner();
});

Production Provider Model

Production deployments should use durable signing and storage. FabrCore exposes provider interfaces so customers can store evidence in a custom SQL schema, data lake, compliance archive, or existing audit database without overloading Orleans entity storage.

Custom Providers
builder.AddFabrCoreServer(options =>
{
    options.UseVerifiableExecution();
    options.UseVerifiableExecutionStore<SqlVerifiableExecutionStore>();
    options.UseVerifiableExecutionSigner<KmsVerifiableExecutionSigner>();
});

Provider Interfaces

InterfacePurpose
IVerifiableExecutionStorePersists records, operation bundles, signatures, verification status, and export data.
IVerifiableExecutionSignerSigns canonical record hashes using local certificates, KMS, HSM, or SPIFFE-backed identity.
IVerifiableExecutionVerifierVerifies record hashes, signatures, chain continuity, parent spans, and trust bundles.
IVerifiableExecutionContextPlugin/tool-facing API used by FabrCore.Sdk.VerifiableExecution helpers to record DB, HTTP, storage, library, and manual evidence.

External Effects

SPIFFE is not what records a database update. Verifiable execution records the effect when the plugin, tool, wrapper, provider, outbox, or external audit system reports it through FabrCore evidence APIs. SPIFFE can help identify which workload signed the record, but the effect still needs to be attested.

FabrCore automatically records the PluginCall or ToolCall around LLM-invoked methods. Developers still use SDK helpers for the real side effects inside those methods.

Plugin SDK Evidence
using FabrCore.Core.VerifiableExecution;
using FabrCore.Sdk.VerifiableExecution;

public async Task UpdateOrderStatus(string orderId, string status)
{
    await _verifiableExecution.RecordDbEffectAsync(
        operation: "UpdateOrderStatus",
        target: "Orders",
        subject: orderId,
        effect: () => _db.UpdateOrderStatus(orderId, status),
        metadata: new Dictionary<string, string?>
        {
            ["row_key_hash"] = VerifiableExecutionHash.HashText(orderId),
            ["status_hash"] = VerifiableExecutionHash.HashText(status)
        });
}
HelperUse it for
RecordDbEffectAsyncSQL commands, entity updates, transaction markers, row/key hashes, affected-row summaries.
RecordHttpCallAsyncOutbound API calls with sanitized method, host/path, status code, success flag, and request/response hashes.
RecordStorageEffectAsyncBlob, object, file, bucket, container, path, content hash, ETag, or version metadata.
RecordLibraryCallAsyncImportant local business-library calls such as scoring, pricing, validation, or rules engines.
Important: Direct database, API, storage, or library changes made outside SDK helpers, manual evidence APIs, provider audit, or outbox integration are marked as ExternalEffectsUnverified. The system can prove the FabrCore timeline, but it cannot prove an unreported side effect happened.

SPIFFE Overview

SPIFFE, the Secure Production Identity Framework For Everyone, is an open standard for giving software workloads cryptographic identity across dynamic and heterogeneous environments. The official SPIFFE overview describes how workloads receive short-lived identity documents called SVIDs and use them for mutual authentication through X.509 certificates or JWT tokens.

That maps directly to FabrCore's cross-cluster story: a FabrCore host can sign verifiable execution records with a workload identity, another cluster can verify the signer against a trust bundle, and customers can avoid hard-coding trust to hostnames, IP addresses, or deployment-specific secrets.

Project or platformHow it relates to SPIFFE
SPIREReference implementation that issues and rotates SPIFFE identities.
DaprUses SPIFFE-style workload identity for distributed application trust.
IstioUses SPIFFE identities as part of service-mesh workload authentication.
Consul and cert-managerPart of the broader open-source ecosystem that can implement SPIFFE capabilities.
FabrCoreUses SPIFFE as the default enterprise trust backend for verifiable execution signing and cross-cluster verification, while preserving pluggable signer providers.

Where SPIFFE Fits

SPIFFE is FabrCore's default workload-identity trust path for enterprise and cross-cluster verification. It is what you choose when another workload, another FabrCore cluster, or an external verifier needs a standard way to trust the signing identity of this host. It does not replace FabrCore user handles, agent handles, agent aliases, ACLs, or application authorization.

Use SPIFFE by default for enterprise and cross-cluster trust. Use local certificate, certificate chain, KMS, or HSM signing providers when the cluster controls its own trust boundary or a customer needs a different key-management implementation.

Verification Flow

  1. A verifier requests an operation bundle by TraceId from the producing cluster or receives it attached to a cross-cluster response.
  2. The verifier canonicalizes each record and recomputes hashes.
  3. The verifier checks signatures against the configured trust roots or SPIFFE trust bundle.
  4. The verifier validates chain continuity, parent spans, terminal status, and expected record kinds.
  5. The verifier reports valid, invalid, incomplete, untrusted signer, missing parent, corrupted signature, or unverified external effects.

Pitfalls

  • Do not promise that verifiable execution proves the LLM was correct. It proves the recorded execution evidence is intact.
  • Do not treat SPIFFE as required for every deployment. It is the default enterprise trust path, but many customers only need local, certificate, KMS, or HSM-backed signing.
  • Do not store sensitive prompts or payloads by default. Prefer hashes, redaction, and explicit capture policies.
  • Do not put all evidence into Orleans state by default. Use the provider model for durable SQL or custom audit storage.
  • Do not let plugins make important side effects without SDK helpers, manual evidence calls, provider audit, or outbox integration if customers need verification.
Related docs

See Monitoring for live visibility, Telemetry for OpenTelemetry traces, Tools for plugin guidance, and Communication for message and event lineage.

Documentation