Go SDK
Use veriproof.app/sdk/go to protect application-owned actions. Add an adapter when the adapter owns the model call you need to protect.
Requirements
- Go 1.26.6 or later
- A VeriProof application SDK key stored outside source control
- Network access to Server Ingest, or a licensed Edge Gateway on the application’s local network
Install
Use the module proxy and version shown in Tools and SDKs. Install only the modules your application uses:
go get veriproof.app/sdk/[email protected]
go get veriproof.app/sdk/go/adapter/[email protected]
go get veriproof.app/sdk/go/adapter/[email protected]
go get veriproof.app/sdk/go/adapter/[email protected]The adapter modules depend on the core module. The core module does not depend on an adapter, a portal package, or a workspace project.
Govern one action
Set VERIPROOF_API_KEY, then create one client. The key identifies the tenant and application, so the client does not need a separate application ID.
import (
"context"
"time"
veriproof "veriproof.app/sdk/go"
governmentpublicsector "veriproof.app/sdk/go/verticals/government_public_sector"
)
governance, err := veriproof.FromEnv()
if err != nil {
return err
}
defer func() {
shutdownContext, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = governance.Shutdown(shutdownContext)
}()
type eligibilityRequest struct {
MonthlyIncomeUSD float64 `json:"monthly_income_usd"`
Program string `json:"program"`
}
type eligibilityResult struct {
Outcome string `json:"outcome"`
}
result := veriproof.Govern(
ctx,
governance,
"benefits.eligibility.evaluate",
eligibilityRequest{
MonthlyIncomeUSD: 1850,
Program: "housing_assistance",
},
func(ctx context.Context, action veriproof.GovernedActionContext[eligibilityRequest]) (eligibilityResult, error) {
if err := action.ThrowIfStopped(); err != nil {
return eligibilityResult{}, err
}
return evaluateEligibility(ctx, action.Input)
},
veriproof.GovernOptions{
Facts: map[string]any{
"monthly_income_usd": 1850,
"program": "housing_assistance",
},
Industry: []veriproof.IndustryFact{
governmentpublicsector.BenefitsEligibilityDecisionTypeInitialEligibilityApproved.Fact(),
},
},
)
if result.Completed() && result.Value != nil {
publish(*result.Value)
}Govern checks the input before it calls evaluateEligibility. It checks output before release through result.Value.
Only these statuses can release a value:
completedcompleted_with_warningtransformed
A blocked, stopped, timed-out, failed, or review-required result has no released value. Never release a value from a blocked result, which the portal shows as Stopped by policy. Use ReasonCode, Message, EvidenceReference, and Review to handle the typed result.
Supply policy fields
Use generated industry values for shared terms. Use Facts and WorkflowFacts for application-specific data. Both reach the active application field contract and can be required, type checked, and restricted to allowed values.
An application can emit a custom field before a rule uses it. The field then appears in the application’s policy-data view. A governance engineer can also add a rule field first; the setup view shows whether the SDK must supply it.
Do not place VeriProof provenance keys in application facts. VeriProof owns its session and evidence attributes.
Handle an emergency stop
Pass the governed context into child work and check its stop signal before an external side effect:
func reserveFunds(ctx context.Context, action veriproof.GovernedActionContext[paymentRequest]) (receipt, error) {
if err := action.ThrowIfStopped(); err != nil {
return receipt{}, err
}
return ledger.Reserve(ctx, action.IdempotencyKey, action.Input)
}A live Stop directive applies only to the matching run. The SDK persists it, signals the run, and then sends its acknowledgement. It does not terminate the Go process. A non-cooperative action can return completion_unknown; reconcile the application side effect before retrying it.
Continue after human review
Save every review checkpoint in a protected workflow store. The supplied SQLite store provides a process-safe default for one application service:
store, err := veriproof.NewSQLiteReviewStore("./state/veriproof-review.db")
if err != nil {
return err
}
defer store.Close()
reviews, err := veriproof.NewHumanReviewRuntime[eligibilityRequest, eligibilityResult](
governance,
veriproof.HumanReviewOptions[eligibilityRequest]{
Store: store,
Revalidate: revalidateCurrentState,
},
)
if err != nil {
return err
}When Govern returns review_required, call reviews.Save with its checkpoint. In the callback route, pass the unchanged body and all callback headers to reviews.Receive. Signature verification happens before JSON decoding.
The runtime checks each callback against the signing keys VeriProof publishes at your endpoint. If your host can’t reach VeriProof, set WebhookKeys to a provider from veriproof.NewPinnedWebhookKeySet(keySetJSON). To check review event webhooks, call veriproof.VerifyWebhook with the key set, your whsec_ subscription secret, or both.
Run reviews.Resume outside the callback request. It reloads the stored checkpoint, validates the signed outcome, rechecks current policy and application state, and executes an approved action at most once. A follow-up keeps the checkpoint paused. A rejection, cancellation, or expiry does not run the action.
If the application no longer needs the paused action, call reviews.Cancel with the saved checkpoint. Select the reason that describes the application event, such as ReviewCancellationReasonParentWorkflowEnded. VeriProof remains authoritative for the review case and delivers its terminal signed outcome. Repeating the same cancellation is safe because the runtime derives a stable idempotency key.
If a resumed side effect may have run but completion is uncertain, the store keeps the action fenced. Call reviews.Reconcile only after the application confirms whether that side effect completed.
Core Human Review uses a 12-field bounded brief and a response and resume-mode matrix. route_to_revision starts application-owned revision work and never runs the superseded payload. Private-note content remains in VeriProof and is excluded from the callback.
Your application owns its business-side idempotency key and reconciliation check. A signed approval does not make an external side effect idempotent.
Use Server Ingest or Edge Gateway
Server Ingest is the default transport. Set VERIPROOF_ENDPOINT only when VeriProof provides a different ingest base URL.
For a licensed Edge Gateway, set VERIPROOF_EDGE_ENDPOINT to its local endpoint. Policy evaluation and evidence acceptance stay on the local hot path. Gateway synchronization with VeriProof runs separately and retries after an outage.
Test without a VeriProof account
Use the in-memory harness for deterministic unit tests:
harness := veriproof.NewTestHarness().RespondWith(veriproof.TestPolicyDecision{
Verdict: veriproof.PolicyDeny,
ReasonCode: "amount_requires_review",
Message: "The requested amount needs a reviewer.",
})
result := veriproof.Govern(
context.Background(),
harness.Veriproof,
"payment.release",
request,
releasePayment,
veriproof.GovernOptions{},
)The harness can return allow, warn, transform, deny, review, degraded, timeout, cancellation, and stop outcomes. It can also enforce a field contract. Use Server Ingest or Edge integration tests for transport qualification.
Framework and provider adapters
| Framework | Package | Checks | Not covered |
|---|---|---|---|
| Anthropic SDK Go | veriproof.app/sdk/go/adapter/anthropic | One explicit non-streaming Messages call and its selected text result | Streaming, provider-hosted tools, raw direct clients, and opaque application tool loops. |
| LangChainGo | veriproof.app/sdk/go/adapter/langchaingo | One explicit text-only non-streaming model operation and its result | Streaming, binary or unsupported-role content, chains, agents, or tools that bypass the adapter, and raw direct clients. |
| OpenAI Go | veriproof.app/sdk/go/adapter/openai | One explicit foreground non-streaming Responses call and its selected text result | Streaming, background responses, provider-hosted tools, and raw direct clients. |
Each adapter releases only the authorized GovernedResult.Value. Protect every application-owned tool side effect with its own Govern call.
See Core Human Review for the lifecycle contract and the runnable Go receiver guide for callback hosting.